From e29942a07432de7f5c18d51aa323508e5c35188e Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 20 Oct 2014 18:23:10 +0400 Subject: [PATCH 01/96] changelog: added current development version section --- stuff/doc_pages/changelog.dox | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stuff/doc_pages/changelog.dox b/stuff/doc_pages/changelog.dox index 2448be7..334a291 100644 --- a/stuff/doc_pages/changelog.dox +++ b/stuff/doc_pages/changelog.dox @@ -5,6 +5,10 @@ TNeoKernel changelog +\section changelog_current Current development version (BETA) + + - *No changes yet* + \section changelog_v1_03 v1.03 Release date: 2014-10-20. From 518cf87529d418793141aaf7eefb086678e5a3e1 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 20 Oct 2014 18:33:27 +0400 Subject: [PATCH 02/96] fixed a couple of typos in documentation --- examples/queue_eventgrp_conn/readme.txt | 4 ++-- src/core/tn_eventgrp.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/queue_eventgrp_conn/readme.txt b/examples/queue_eventgrp_conn/readme.txt index 1df4a68..6f42681 100644 --- a/examples/queue_eventgrp_conn/readme.txt +++ b/examples/queue_eventgrp_conn/readme.txt @@ -31,7 +31,7 @@ Event group connection is a perfectly fine solution. If the kernel doesn't offer a mechanism for that, programmer usually have to use polling services on these queues and sleep for a few system ticks. Obviously, this approach has serious drawbacks: we have a lot of useless context switches, and response for -the message gets much slower. Actually, we lost the main goal of the preemtive -kernel when we use polling services like that. +the message gets much slower. Actually, we lost the main goal of the +preemptive kernel when we use polling services like that. diff --git a/src/core/tn_eventgrp.h b/src/core/tn_eventgrp.h index 1e67004..8cc1b32 100644 --- a/src/core/tn_eventgrp.h +++ b/src/core/tn_eventgrp.h @@ -63,7 +63,7 @@ * use polling services on these queues and sleep for a few system ticks. * Obviously, this approach has serious drawbacks: we have a lot of useless * context switches, and response for the message gets much slower. Actually, - * we lost the main goal of the preemtive kernel when we use polling services + * we lost the main goal of the preemptive kernel when we use polling services * like that. * * TNeoKernel offers a solution: an event group can be connected to other From ba56cc054f7e80fa0ac039a9b003a8e6495c4a53 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 21 Oct 2014 11:47:44 +0400 Subject: [PATCH 03/96] the page 'differences from TNKernel' updated: added event group connection --- src/core/tn_eventgrp.h | 3 ++- stuff/doc_pages/tnkernel_diff.dox | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/core/tn_eventgrp.h b/src/core/tn_eventgrp.h index 8cc1b32..3940fe4 100644 --- a/src/core/tn_eventgrp.h +++ b/src/core/tn_eventgrp.h @@ -56,7 +56,8 @@ * examples are: * * - wait for a message from the queue(s) plus wait for some - * application-dependent event; + * application-dependent event (such as a flag to finish the task, or + * whatever); * - wait for messages from multiple queues. * * If the kernel doesn't offer a mechanism for that, programmer usually have to diff --git a/stuff/doc_pages/tnkernel_diff.dox b/stuff/doc_pages/tnkernel_diff.dox index 81bb1c6..186d6b4 100644 --- a/stuff/doc_pages/tnkernel_diff.dox +++ b/stuff/doc_pages/tnkernel_diff.dox @@ -132,6 +132,29 @@ In original TNKernel, system functions refused to perform job and returned `#TER \section tnkernel_new_features New features +\subsection tnkernel_new_features__eventgrp_conn Event group connection + +Sometimes task needs to wait for different system events, the most common +examples are: + +- wait for a message from the queue(s) plus wait for some + application-dependent event (such as a flag to finish the task, or + whatever); +- wait for messages from multiple queues. + +If the kernel doesn't offer a mechanism for that, programmer usually have to +use polling services on these queues and sleep for a few system ticks. +Obviously, this approach has serious drawbacks: we have a lot of useless +context switches, and response for the message gets much slower. Actually, we +lost the main goal of the preemptive kernel when we use polling services like +that. + +TNeoKernel (since \ref changelog_v1_03) offers a solution: an event group can +be connected to other kernel objects, and these objects will maintain certain +flags inside that event group automatically. + +Refer to the section \ref eventgrp_connect for details. + \subsection tnkernel_new_features__timer Timers Support of timers was added since TNeoKernel \ref changelog_v1_02. From 29ee764cb9930ddb48f557a17cc41acdeefaff2a Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 21 Oct 2014 14:14:47 +0400 Subject: [PATCH 04/96] working on Exchange object: the very basics implemented --- .../tneokernel.X/nbproject/configurations.xml | 1 + src/core/tn_common.h | 1 + src/core/tn_exch.c | 208 ++++++++++++++ src/core/tn_exch.h | 267 ++++++++++++++++++ src/tn.h | 1 + stuff/doc_pages/mainpage.dox | 1 + 6 files changed, 479 insertions(+) create mode 100644 src/core/tn_exch.c create mode 100644 src/core/tn_exch.h diff --git a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml index 8007b9b..3d2ff42 100644 --- a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml +++ b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml @@ -28,6 +28,7 @@ ../../../core/tn_eventgrp.c ../../../core/tn_fmem.c ../../../core/tn_timer.c + ../../../core/tn_exch.c id_exch != TN_ID_EXCHANGE){ + rc = TN_RC_INVALID_OBJ; + } + + return rc; +} + +static inline enum TN_RCode _check_param_create( + struct TN_Exch *exch + ) +{ + enum TN_RCode rc = TN_RC_OK; + + if (exch == NULL){ + rc = TN_RC_WPARAM; + } else if (exch->id_exch == TN_ID_EXCHANGE){ + rc = TN_RC_WPARAM; + } + + return rc; +} + +#else +# define _check_param_generic(exch) (TN_RC_OK) +# define _check_param_create(exch) (TN_RC_OK) +#endif +// }}} + + + +/******************************************************************************* + * PUBLIC FUNCTIONS + ******************************************************************************/ + +/* + * See comments in the header file (tn_exch.h) + */ +enum TN_RCode tn_exch_create( + struct TN_Exch *exch, + TN_UWord *data, + unsigned int size + ) +{ + enum TN_RCode rc = _check_param_create(exch); + if (rc != TN_RC_OK){ + goto out; + } + + //-- basic check: data should not be NULL, + // and size should not be 0 + if (data == NULL || size == 0){ + rc = TN_RC_WPARAM; + goto out; + } + + + //-- check that `data` is aligned properly + { + unsigned long data_aligned + = TN_MAKE_ALIG_SIZE((unsigned long)data); + + if (data_aligned != (unsigned int)data){ + rc = TN_RC_WPARAM; + goto out; + } + } + + //-- check that `size` is aligned properly + { + unsigned int size_aligned = TN_MAKE_ALIG_SIZE(size); + if (size_aligned != size){ + rc = TN_RC_WPARAM; + goto out; + } + } + + //-- checks are done; proceed to actual creation + exch->data = data; + exch->size = size; + + //-- reset links_list + tn_list_reset(&(exch->links_list)); + + //-- set id + exch->id_exch = TN_ID_EXCHANGE; + +out: + return rc; +} + +/* + * See comments in the header file (tn_exch.h) + */ +enum TN_RCode tn_exch_delete(struct TN_Exch *exch) +{ + enum TN_RCode rc = _check_param_generic(exch); + + if (rc != TN_RC_OK){ + //-- just return rc as it is + } else if (!tn_is_task_context()){ + rc = TN_RC_WCONTEXT; + } else { + TN_INTSAVE_DATA; + + TN_INT_DIS_SAVE(); + exch->id_exch = 0; //-- Exchange object does not exist now + TN_INT_RESTORE(); + } + + return rc; +} + + + + + + +/******************************************************************************* + * PROTECTED FUNCTIONS + ******************************************************************************/ + + + + diff --git a/src/core/tn_exch.h b/src/core/tn_exch.h new file mode 100644 index 0000000..73eed72 --- /dev/null +++ b/src/core/tn_exch.h @@ -0,0 +1,267 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * \file + * + * Exchange + * + */ + + +#ifndef _TN_EXCH_H +#define _TN_EXCH_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "tn_list.h" +#include "tn_common.h" +#include "tn_sys.h" + + + +/******************************************************************************* + * EXTERN TYPES + ******************************************************************************/ + +struct TN_DQueue; +struct TN_FMem; +struct TN_EventGrp; + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +struct TN_Exch; + +typedef void (TN_ExchCallbackFunc)( + struct TN_Exch *exch, + TN_UWord *data, + unsigned int size, + void *p_user_data + ); + + +/** + * Exchange + */ +struct TN_Exch { + /// + /// List of all connected links (`struct TN_ExchLinkQueue`, etc) + struct TN_ListItem links_list; + /// + /// Pointer to actual exchange data + TN_UWord *data; + /// + /// Size of the exchange data, should be a multiple of `sizeof(#TN_UWord)` + unsigned int size; + /// + /// id for object validity verification + enum TN_ObjId id_exch; +}; + +struct TN_ExchLinkQueue { + /// + /// A list item to be included in the exchange links list + struct TN_ListItem links_list_item; + /// + /// Poiner to the queue in which exchange should send messages + struct TN_DQueue *queue; + /// + /// Poiner to the fixed memory pool from which memory should be + /// allocated for the message. + /// + /// NOTE: if the size of exchange item is <= `sizeof(void *)`, + /// fixed memory pool might be not used (`NULL`): then, data + /// will be passed by the queue only. + /// + /// If fixed memory pool is used, its size should match the size of + /// exchange data. + struct TN_FMem *fmem; +}; + +struct TN_ExchLinkEvent { + /// + /// A list item to be included in the exchange links list + struct TN_ListItem links_list_item; + /// + /// Poiner to the eventgrp to set event in + struct TN_EventGrp *eventgrp; + /// + /// Flags pattern to set in the given event group + TN_UWord pattern; +}; + +struct TN_ExchLinkCallback { + /// + /// A list item to be included in the exchange links list + struct TN_ListItem links_list_item; + /// + /// Poiner to the eventgrp to set event in + TN_ExchCallbackFunc *func; + /// + /// User data to be given to callback function + void *p_user_data; +}; + + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +/** + * Convenience macro for the definition of buffer for data. See + * `tn_exch_create()` for usage example. TODO: example + * + * @param name + * C variable name of the buffer array (this name should be given + * to the `tn_exch_create()` function as the `data` argument) + * @param item_type + * Type of item in the memory pool, like `struct MyExchangeData`. + */ +#define TN_EXCH_DATA_BUF_DEF(name, item_type) \ + TN_UWord name[ \ + (TN_MAKE_ALIG_SIZE(sizeof(item_type)) / sizeof(TN_UWord)) \ + ] + + +/******************************************************************************* + * PUBLIC FUNCTION PROTOTYPES + ******************************************************************************/ + +/** + * Construct the exchange object. `id_exch` field should not contain + * `#TN_ID_EXCHANGE`, otherwise, `#TN_RC_WPARAM` is returned. + * + * Note that `data` and `size` should be a multiple of `sizeof(#TN_UWord)`. + * + * For the definition of buffer, convenience macro `TN_EXCH_DATA_BUF_DEF()` + * was invented. + * + * Typical definition looks as follows: + * + * \code{.c} + * //-- type of data that exchange object stores + * struct MyExchangeData { + * // ... arbitrary fields ... + * }; + * + * //-- define buffer for memory pool + * TN_EXCH_DATA_BUF_DEF(my_exch_buf, struct MyExchangeData); + * + * //-- define memory pool structure + * struct TN_Exch my_exch; + * \endcode + * + * And then, construct your `my_exch` as follows: + * + * \code{.c} + * enum TN_RCode rc; + * rc = tn_exch_create( &my_exch, + * my_exch_buf, + * TN_MAKE_ALIG_SIZE(sizeof(struct MyExchangeData)) + * ); + * if (rc != TN_RC_OK){ + * //-- handle error + * } + * \endcode + * + * If given `data` and/or `size` aren't aligned properly, `#TN_RC_WPARAM` is + * returned. + * + * $(TN_CALL_FROM_TASK) + * $(TN_CALL_FROM_ISR) + * $(TN_LEGEND_LINK) + * + * @param exch + * Pointer to already allocated `struct TN_Exch` + * @param data + * Pointer to already allocated exchange data buffer, its size must be a + * multiple of `sizeof(#TN_UWord)` + * @param size + * Size of the exchange data buffer, must be a multiple of + * `sizeof(#TN_UWord)` + * + * @return + * * `#TN_RC_OK` if exchange object was successfully created; + * * `#TN_RC_WPARAM` if wrong params were given. + */ +enum TN_RCode tn_exch_create( + struct TN_Exch *exch, + TN_UWord *data, + unsigned int size + ); + +/** + * Destruct the exchange object. + * + * $(TN_CALL_FROM_TASK) + * $(TN_LEGEND_LINK) + * + * @param exch exchange object to destruct + * + * @return + * * `#TN_RC_OK` if object was successfully deleted; + * * `#TN_RC_WCONTEXT` if called from wrong context; + * * If `#TN_CHECK_PARAM` is non-zero, additional return codes + * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`. + */ +enum TN_RCode tn_exch_delete(struct TN_Exch *exch); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // _TN_EXCH_H + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/tn.h b/src/tn.h index ed4c359..a2d3f50 100644 --- a/src/tn.h +++ b/src/tn.h @@ -57,6 +57,7 @@ #include "core/tn_sem.h" #include "core/tn_tasks.h" #include "core/tn_list.h" +#include "core/tn_exch.h" #include "core/tn_timer.h" diff --git a/stuff/doc_pages/mainpage.dox b/stuff/doc_pages/mainpage.dox index 0a39bea..f99783c 100644 --- a/stuff/doc_pages/mainpage.dox +++ b/stuff/doc_pages/mainpage.dox @@ -42,6 +42,7 @@ API reference: - \ref tn_fmem.h "Fixed-memory blocks pool" - \ref tn_eventgrp.h "Event groups" - \ref tn_dqueue.h "Data queues" + - \ref tn_exch.h "Exchange" - \ref tn_timer.h "Timers" From 5dc0a374de0ef472e7601771258b7fe740bd6353 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 21 Oct 2014 16:52:51 +0400 Subject: [PATCH 05/96] working on Exchange object: added drafts of tn_exch_read()/write() --- src/core/tn_exch.c | 99 ++++++++++++++++++++++++++++++++++++++++-- src/core/tn_exch.h | 11 ++--- src/core/tn_internal.h | 18 ++++++++ 3 files changed, 119 insertions(+), 9 deletions(-) diff --git a/src/core/tn_exch.c b/src/core/tn_exch.c index 3c3887f..1202893 100644 --- a/src/core/tn_exch.c +++ b/src/core/tn_exch.c @@ -46,9 +46,6 @@ //-- header of current module #include "tn_exch.h" -//-- header of other needed modules -#include "tn_tasks.h" - @@ -110,6 +107,30 @@ static inline enum TN_RCode _check_param_create( #endif // }}} +/** + * @param size size in bytes + */ +void _memcpy_uword(TN_UWord *tgt, const TN_UWord *src, unsigned int size) +{ + //TODO: optimize + int uwords_cnt = size / sizeof(TN_UWord); + int i; + for (i = 0; i < uwords_cnt; i++){ + *tgt++ = *src++; + } +} + +enum TN_RCode _notify_all( + struct TN_Exch *exch + ) +{ + enum TN_RCode rc = TN_RC_OK; + + //TODO + + return rc; +} + /******************************************************************************* @@ -121,7 +142,7 @@ static inline enum TN_RCode _check_param_create( */ enum TN_RCode tn_exch_create( struct TN_Exch *exch, - TN_UWord *data, + void *data, unsigned int size ) { @@ -194,6 +215,49 @@ enum TN_RCode tn_exch_delete(struct TN_Exch *exch) return rc; } +enum TN_RCode tn_exch_write( + struct TN_Exch *exch, + const void *data + ) +{ + enum TN_RCode rc = _check_param_generic(exch); + + if (rc != TN_RC_OK){ + //-- just return rc as it is + } else if (!tn_is_task_context()){ + rc = TN_RC_WCONTEXT; + } else { + TN_INTSAVE_DATA; + + TN_INT_DIS_SAVE(); + rc =_tn_exch_write(exch, data); + TN_INT_RESTORE(); + } + + return rc; +} + +enum TN_RCode tn_exch_read( + struct TN_Exch *exch, + void *data_tgt + ) +{ + enum TN_RCode rc = _check_param_generic(exch); + + if (rc != TN_RC_OK){ + //-- just return rc as it is + } else if (!tn_is_task_context()){ + rc = TN_RC_WCONTEXT; + } else { + TN_INTSAVE_DATA; + + TN_INT_DIS_SAVE(); + rc = _tn_exch_read(exch, data_tgt); + TN_INT_RESTORE(); + } + + return rc; +} @@ -203,6 +267,33 @@ enum TN_RCode tn_exch_delete(struct TN_Exch *exch) * PROTECTED FUNCTIONS ******************************************************************************/ +/** + * See comments in the tn_internal.h file + */ +enum TN_RCode _tn_exch_write( + struct TN_Exch *exch, + const void *data + ) +{ + _memcpy_uword((TN_UWord *)exch->data, (const TN_UWord *)data, exch->size); + + _notify_all(exch); + + return TN_RC_OK; +} + +/** + * See comments in the tn_internal.h file + */ +enum TN_RCode _tn_exch_read( + struct TN_Exch *exch, + void *data_tgt + ) +{ + _memcpy_uword((TN_UWord *)data_tgt, (const TN_UWord *)exch->data, exch->size); + + return TN_RC_OK; +} diff --git a/src/core/tn_exch.h b/src/core/tn_exch.h index 73eed72..80f1e77 100644 --- a/src/core/tn_exch.h +++ b/src/core/tn_exch.h @@ -77,7 +77,7 @@ struct TN_Exch; typedef void (TN_ExchCallbackFunc)( struct TN_Exch *exch, - TN_UWord *data, + void *data, unsigned int size, void *p_user_data ); @@ -92,9 +92,10 @@ struct TN_Exch { struct TN_ListItem links_list; /// /// Pointer to actual exchange data - TN_UWord *data; + void *data; /// - /// Size of the exchange data, should be a multiple of `sizeof(#TN_UWord)` + /// Size of the exchange data in bytes, should be a multiple of + /// `sizeof(#TN_UWord)` unsigned int size; /// /// id for object validity verification @@ -224,7 +225,7 @@ struct TN_ExchLinkCallback { * Pointer to already allocated exchange data buffer, its size must be a * multiple of `sizeof(#TN_UWord)` * @param size - * Size of the exchange data buffer, must be a multiple of + * Size of the exchange data buffer in bytes, must be a multiple of * `sizeof(#TN_UWord)` * * @return @@ -233,7 +234,7 @@ struct TN_ExchLinkCallback { */ enum TN_RCode tn_exch_create( struct TN_Exch *exch, - TN_UWord *data, + void *data, unsigned int size ); diff --git a/src/core/tn_internal.h b/src/core/tn_internal.h index 12754e8..2106cb6 100644 --- a/src/core/tn_internal.h +++ b/src/core/tn_internal.h @@ -68,6 +68,7 @@ extern "C" { /*}*/ struct TN_Mutex; struct TN_ListItem; struct TN_Timer; +struct TN_Exch; @@ -527,6 +528,23 @@ enum TN_RCode _tn_eventgrp_link_manage( BOOL set ); + + + +/******************************************************************************* + * tn_exch.c + ******************************************************************************/ + +enum TN_RCode _tn_exch_write( + struct TN_Exch *exch, + const void *data + ); + +enum TN_RCode _tn_exch_read( + struct TN_Exch *exch, + void *data_tgt + ); + #endif // _TN_INTERNAL_H From 9ee406716752f42247e202bf7eb2ed7737e31e18 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 21 Oct 2014 19:00:35 +0400 Subject: [PATCH 06/96] added tn_exch_link, but it is not used yet --- src/core/tn_common.h | 1 + src/core/tn_exch_link.c | 213 ++++++++++++++++++++++++++++++++++++++++ src/core/tn_exch_link.h | 134 +++++++++++++++++++++++++ src/core/tn_internal.h | 23 +++++ 4 files changed, 371 insertions(+) create mode 100644 src/core/tn_exch_link.c create mode 100644 src/core/tn_exch_link.h diff --git a/src/core/tn_common.h b/src/core/tn_common.h index 87d6d21..c875c80 100644 --- a/src/core/tn_common.h +++ b/src/core/tn_common.h @@ -93,6 +93,7 @@ enum TN_ObjId { TN_ID_MUTEX = 0x17129E45, //!< id for mutexes TN_ID_TIMER = 0x9A937FBC, //!< id for timers TN_ID_EXCHANGE = 0x32b7c072, //!< id for exchange objects + TN_ID_EXCHANGE_LINK = 0x24d36f35, //!< id for exchange objects }; /** diff --git a/src/core/tn_exch_link.c b/src/core/tn_exch_link.c new file mode 100644 index 0000000..4e5ee44 --- /dev/null +++ b/src/core/tn_exch_link.c @@ -0,0 +1,213 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +//-- common tnkernel headers +#include "tn_common.h" +#include "tn_sys.h" +#include "tn_internal.h" + +//-- header of current module +#include "tn_exch_link.h" + + + +/******************************************************************************* + * PUBLIC DATA + ******************************************************************************/ + + +/******************************************************************************* + * PRIVATE DATA + ******************************************************************************/ + +static struct TN_ExchLink_VTable _vtable = {}; +static BOOL _vtable_initialized = FALSE; + + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + + + + +/******************************************************************************* + * PRIVATE FUNCTIONS + ******************************************************************************/ + +//-- Additional param checking {{{ +#if TN_CHECK_PARAM +static inline enum TN_RCode _check_param_generic( + struct TN_ExchLink *exch_link + ) +{ + enum TN_RCode rc = TN_RC_OK; + + if (exch_link == NULL){ + rc = TN_RC_WPARAM; + } else if (exch_link->id_exch_link != TN_ID_EXCHANGE_LINK){ + rc = TN_RC_INVALID_OBJ; + } + + return rc; +} + +static inline enum TN_RCode _check_param_create( + struct TN_ExchLink *exch_link + ) +{ + enum TN_RCode rc = TN_RC_OK; + + if (exch_link == NULL){ + rc = TN_RC_WPARAM; + } else if (exch_link->id_exch_link == TN_ID_EXCHANGE_LINK){ + rc = TN_RC_WPARAM; + } + + return rc; +} + +#else +# define _check_param_generic(exch_link) (TN_RC_OK) +# define _check_param_create(exch_link) (TN_RC_OK) +#endif +// }}} + +static enum TN_RCode _notify(struct TN_ExchLink *exch_link) +{ + //-- should never be here + _TN_FATAL_ERROR("called notify() of base TN_ExchLink"); + return TN_RC_INTERNAL; +} + +static enum TN_RCode _dtor(struct TN_ExchLink *exch_link) +{ + //-- nothing to do here + return TN_RC_OK; +} + +static void _vtable_init() +{ + if (!_vtable_initialized){ + _vtable.notify = _notify; + _vtable.dtor = _dtor; + + _vtable_initialized = TRUE; + } +} + + + + + + + +/******************************************************************************* + * PROTECTED FUNCTIONS + ******************************************************************************/ + +/** + * See comments in the tn_internal.h file + */ +const struct TN_ExchLink_VTable *_tn_exch_link_vtable(void) +{ + _vtable_init(); + return &_vtable; +} + + +/** + * See comments in the tn_internal.h file + */ +enum TN_RCode _tn_exch_link_create( + struct TN_ExchLink *exch_link + ) +{ + enum TN_RCode rc = _check_param_create(exch_link); + + if (rc != TN_RC_OK){ + //-- just return rc as it is + } else { + _vtable_init(); + exch_link->vtable = &_vtable; + + tn_list_reset(&(exch_link->links_list_item)); + + exch_link->id_exch_link = TN_ID_EXCHANGE_LINK; + } + + return rc; +} + + +/** + * See comments in the tn_internal.h file + */ +enum TN_RCode _tn_exch_link_notify( + struct TN_ExchLink *exch_link + ) +{ + enum TN_RCode rc = _check_param_generic(exch_link); + + if (rc != TN_RC_OK){ + //-- just return rc as it is + } else { + rc = exch_link->vtable->notify(exch_link); + } + + return rc; +} + + +/** + * See comments in the tn_internal.h file + */ +enum TN_RCode _tn_exch_link_delete( + struct TN_ExchLink *exch_link + ) +{ + return exch_link->vtable->dtor(exch_link); +} + + + diff --git a/src/core/tn_exch_link.h b/src/core/tn_exch_link.h new file mode 100644 index 0000000..01d59f7 --- /dev/null +++ b/src/core/tn_exch_link.h @@ -0,0 +1,134 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * \file + * + * Exchange link (base structure). For internal kernel usage only. + * + */ + + +#ifndef _TN_EXCH_LINK_H +#define _TN_EXCH_LINK_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "tn_list.h" + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +struct TN_ExchLink; + + +/** + * Virtual method prototype: notify. + * + * For internal kernel usage only. + */ +typedef enum TN_RCode (TN_ExchLink_Notify)(struct TN_ExchLink *exch); + +/** + * Virtual method prototype: destructor. + * + * For internal kernel usage only. + */ +typedef enum TN_RCode (TN_ExchLink_Dtor) (struct TN_ExchLink *exch); + +/** + * Virtual methods table for each type of \ref tn_exch.h "exchange" link. + * + * For internal kernel usage only. + */ +struct TN_ExchLink_VTable { + TN_ExchLink_Notify *notify; + TN_ExchLink_Dtor *dtor; +}; + +/** + * Base structure for \ref tn_exch.h "exchange" link. + * + * For internal kernel usage only. + */ +struct TN_ExchLink { + /// + /// A list item to be included in the exchange links list + struct TN_ListItem links_list_item; + /// + /// Virtual methods table + struct TN_ExchLink_VTable *vtable; + /// + /// id for object validity verification + enum TN_ObjId id_exch_link; +}; + + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +/******************************************************************************* + * PUBLIC FUNCTION PROTOTYPES + ******************************************************************************/ + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // _TN_EXCH_LINK_H + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/tn_internal.h b/src/core/tn_internal.h index 2106cb6..d94c03e 100644 --- a/src/core/tn_internal.h +++ b/src/core/tn_internal.h @@ -69,6 +69,7 @@ struct TN_Mutex; struct TN_ListItem; struct TN_Timer; struct TN_Exch; +struct TN_ExchLink; @@ -545,6 +546,28 @@ enum TN_RCode _tn_exch_read( void *data_tgt ); + + +/******************************************************************************* + * tn_exch_link.c + ******************************************************************************/ + +const struct TN_ExchLink_VTable *_tn_exch_link_vtable(void); + +enum TN_RCode _tn_exch_link_create( + struct TN_ExchLink *exch_link + ); + +enum TN_RCode _tn_exch_link_notify( + struct TN_ExchLink *exch_link + ); + +enum TN_RCode _tn_exch_link_delete( + struct TN_ExchLink *exch_link + ); + + + #endif // _TN_INTERNAL_H From 11dd5e368f868f91adb9fa2e5126dff5acef3701 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 21 Oct 2014 19:23:14 +0400 Subject: [PATCH 07/96] removed common internal header tn_internal.h, added separate headers internal/_tn_...h --- .../tneokernel.X/nbproject/configurations.xml | 3 +- src/core/internal/_tn_eventgrp.h | 109 ++++ src/core/internal/_tn_exch.h | 105 ++++ src/core/internal/_tn_exch_link.h | 109 ++++ src/core/internal/_tn_mutex.h | 113 ++++ src/core/internal/_tn_sys.h | 196 ++++++ src/core/internal/_tn_tasks.h | 276 +++++++++ src/core/internal/_tn_timer.h | 154 +++++ src/core/tn_dqueue.c | 6 +- src/core/tn_eventgrp.c | 12 +- src/core/tn_exch.c | 9 +- src/core/tn_exch_link.c | 13 +- src/core/tn_fmem.c | 5 +- src/core/tn_internal.h | 573 ------------------ src/core/tn_mutex.c | 11 +- src/core/tn_sem.c | 5 +- src/core/tn_sys.c | 11 +- src/core/tn_tasks.c | 23 +- src/core/tn_timer.c | 21 +- stuff/doxygen/tn_doxyfile | 8 +- 20 files changed, 1145 insertions(+), 617 deletions(-) create mode 100644 src/core/internal/_tn_eventgrp.h create mode 100644 src/core/internal/_tn_exch.h create mode 100644 src/core/internal/_tn_exch_link.h create mode 100644 src/core/internal/_tn_mutex.h create mode 100644 src/core/internal/_tn_sys.h create mode 100644 src/core/internal/_tn_tasks.h create mode 100644 src/core/internal/_tn_timer.h delete mode 100644 src/core/tn_internal.h diff --git a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml index 3d2ff42..49d1758 100644 --- a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml +++ b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml @@ -74,7 +74,8 @@ - + diff --git a/src/core/internal/_tn_eventgrp.h b/src/core/internal/_tn_eventgrp.h new file mode 100644 index 0000000..de038c6 --- /dev/null +++ b/src/core/internal/_tn_eventgrp.h @@ -0,0 +1,109 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_EVENTGRP_H +#define __TN_EVENTGRP_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" + + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +/** + * Establish link to the event group + */ +enum TN_RCode _tn_eventgrp_link_set( + struct TN_EGrpLink *eventgrp_link, + struct TN_EventGrp *eventgrp, + TN_UWord pattern + ); + +/** + * Reset link to the event group (no matter whether it is already established) + */ +enum TN_RCode _tn_eventgrp_link_reset( + struct TN_EGrpLink *eventgrp_link + ); + +enum TN_RCode _tn_eventgrp_link_manage( + struct TN_EGrpLink *eventgrp_link, + BOOL set + ); + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_EVENTGRP_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_exch.h b/src/core/internal/_tn_exch.h new file mode 100644 index 0000000..9777f88 --- /dev/null +++ b/src/core/internal/_tn_exch.h @@ -0,0 +1,105 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_EXCH_H +#define __TN_EXCH_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * EXTERNAL TYPES + ******************************************************************************/ + +struct TN_Exch; + + + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +enum TN_RCode _tn_exch_write( + struct TN_Exch *exch, + const void *data + ); + +enum TN_RCode _tn_exch_read( + struct TN_Exch *exch, + void *data_tgt + ); + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_EXCH_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_exch_link.h b/src/core/internal/_tn_exch_link.h new file mode 100644 index 0000000..6d62727 --- /dev/null +++ b/src/core/internal/_tn_exch_link.h @@ -0,0 +1,109 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_EXCH_LINK_H +#define __TN_EXCH_LINK_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * EXTERNAL TYPES + ******************************************************************************/ + +struct TN_ExchLink; + + + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +const struct TN_ExchLink_VTable *_tn_exch_link_vtable(void); + +enum TN_RCode _tn_exch_link_create( + struct TN_ExchLink *exch_link + ); + +enum TN_RCode _tn_exch_link_notify( + struct TN_ExchLink *exch_link + ); + +enum TN_RCode _tn_exch_link_delete( + struct TN_ExchLink *exch_link + ); + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_EXCH_LINK_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_mutex.h b/src/core/internal/_tn_mutex.h new file mode 100644 index 0000000..0f7ae12 --- /dev/null +++ b/src/core/internal/_tn_mutex.h @@ -0,0 +1,113 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_MUTEX_H +#define __TN_MUTEX_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" + + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +#if TN_USE_MUTEXES +/** + * Unlock all mutexes locked by the task + */ +void _tn_mutex_unlock_all_by_task(struct TN_Task *task); + +/** + * Should be called when task finishes waiting + * for mutex with priority inheritance + */ +void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task); + +/** + * Should be called when task winishes waiting + * for any mutex (no matter which algorithm it uses) + */ +void _tn_mutex_on_task_wait_complete(struct TN_Task *task); + +#else +static inline void _tn_mutex_unlock_all_by_task(struct TN_Task *task) {} +static inline void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task) {} +static inline void _tn_mutex_on_task_wait_complete(struct TN_Task *task) {} +#endif + + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_MUTEX_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_sys.h b/src/core/internal/_tn_sys.h new file mode 100644 index 0000000..f147a19 --- /dev/null +++ b/src/core/internal/_tn_sys.h @@ -0,0 +1,196 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_SYS_H +#define __TN_SYS_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "tn_arch.h" +#include "tn_list.h" +#include "tn_tasks.h" + + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +/// list of all ready to run (TN_TASK_STATE_RUNNABLE) tasks +extern struct TN_ListItem tn_ready_list[TN_PRIORITIES_CNT]; + +/// list all created tasks (now it is used for statictic only) +extern struct TN_ListItem tn_create_queue; + +/// count of created tasks +extern volatile int tn_created_tasks_cnt; + +/// system state flags +extern volatile enum TN_StateFlag tn_sys_state; + +/// task that runs now +extern struct TN_Task *tn_curr_run_task; + +/// task that should run as soon as possible (after context switch) +extern struct TN_Task *tn_next_task_to_run; + +/// bitmask of priorities with runnable tasks. +/// lowest priority bit (1 << (TN_PRIORITIES_CNT - 1)) should always be set, +/// since this priority is used by idle task and it is always runnable. +extern volatile unsigned int tn_ready_to_run_bmp; + +/// system time that is get/set by `tn_sys_time_get()`, +/// respectively. +extern volatile unsigned int tn_sys_time_count; + +/// current interrupt nesting count. Used by macros +/// `tn_soft_isr()` and `tn_srs_isr()`. +extern volatile int tn_int_nest_count; + +/// saved task stack pointer. Needed when switching stack pointer from +/// task stack to interrupt stack. +extern void *tn_user_sp; + +/// saved ISR stack pointer. Needed when switching stack pointer from +/// interrupt stack to task stack. +extern void *tn_int_sp; + +/// +/// idle task structure +extern struct TN_Task tn_idle_task; + + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +#if !defined(container_of) +/* given a pointer @ptr to the field @member embedded into type (usually + * struct) @type, return pointer to the embedding instance of @type. */ +#define container_of(ptr, type, member) \ + ((type *)((char *)(ptr)-(char *)(&((type *)0)->member))) +#endif + + +#ifndef TN_DEBUG +# error TN_DEBUG is not defined +#endif + +#if TN_DEBUG +#define _TN_BUG_ON(cond, ...){ \ + if (cond){ \ + _TN_FATAL_ERROR(__VA_ARGS__); \ + } \ +} +#else +#define _TN_BUG_ON(cond) /* nothing */ +#endif + + + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +/** + * Remove all tasks from wait queue, returning the TN_RC_DELETED code. + */ +void _tn_wait_queue_notify_deleted(struct TN_ListItem *wait_queue); + + +/** + * Set flags by bitmask. + * Given flags value will be OR-ed with existing flags. + * + * @return previous tn_sys_state value. + */ +enum TN_StateFlag _tn_sys_state_flags_set(enum TN_StateFlag flags); + +/** + * Clear flags by bitmask + * Given flags value will be inverted and AND-ed with existing flags. + * + * @return previous tn_sys_state value. + */ +enum TN_StateFlag _tn_sys_state_flags_clear(enum TN_StateFlag flags); + +#if TN_MUTEX_DEADLOCK_DETECT +void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task); +#endif + +static inline BOOL _tn_need_context_switch(void) +{ + return (tn_curr_run_task != tn_next_task_to_run); +} + +static inline void _tn_context_switch_pend_if_needed(void) +{ + if (_tn_need_context_switch()){ + _tn_arch_context_switch_pend(); + } +} + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_SYS_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_tasks.h b/src/core/internal/_tn_tasks.h new file mode 100644 index 0000000..c0b20ad --- /dev/null +++ b/src/core/internal/_tn_tasks.h @@ -0,0 +1,276 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_TASKS_H +#define __TN_TASKS_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" + + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +#define _tn_get_task_by_tsk_queue(que) \ + (que ? container_of(que, struct TN_Task, task_queue) : 0) + + + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +/** + * Callback that is given to `_tn_task_first_wait_complete()`, may perform + * any needed actions before waking task up, e.g. set some data in the `struct + * TN_Task` that task is waiting for. + * + * @param task + * Task that is going to be waken up + * @param user_data_1 + * Arbitrary user data given to `_tn_task_first_wait_complete()` + * @param user_data_2 + * Arbitrary user data given to `_tn_task_first_wait_complete()` + */ +typedef void (_TN_CBBeforeTaskWaitComplete)( + struct TN_Task *task, + void *user_data_1, + void *user_data_2 + ); + + +static inline BOOL _tn_task_is_runnable(struct TN_Task *task) +{ + return !!(task->task_state & TN_TASK_STATE_RUNNABLE); +} + +static inline BOOL _tn_task_is_waiting(struct TN_Task *task) +{ + return !!(task->task_state & TN_TASK_STATE_WAIT); +} + +static inline BOOL _tn_task_is_suspended(struct TN_Task *task) +{ + return !!(task->task_state & TN_TASK_STATE_SUSPEND); +} + +static inline BOOL _tn_task_is_dormant(struct TN_Task *task) +{ + return !!(task->task_state & TN_TASK_STATE_DORMANT); +} + +/** + * Should be called when task_state is NONE. + * + * Set RUNNABLE bit in task_state, + * put task on the 'ready queue' for its priority, + * + * if priority is higher than tn_next_task_to_run's priority, + * then set tn_next_task_to_run to this task and return TRUE, + * otherwise return FALSE. + */ +void _tn_task_set_runnable(struct TN_Task *task); + + +/** + * Should be called when task_state has just single RUNNABLE bit set. + * + * Clear RUNNABLE bit, remove task from 'ready queue', determine and set + * new tn_next_task_to_run. + */ +void _tn_task_clear_runnable(struct TN_Task *task); + +void _tn_task_set_waiting( + struct TN_Task *task, + struct TN_ListItem *wait_que, + enum TN_WaitReason wait_reason, + TN_Timeout timeout + ); + +/** + * @param wait_rc return code that will be returned to waiting task + */ +void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc); + +void _tn_task_set_suspended(struct TN_Task *task); +void _tn_task_clear_suspended(struct TN_Task *task); + +void _tn_task_set_dormant(struct TN_Task* task); + +void _tn_task_clear_dormant(struct TN_Task *task); + +enum TN_RCode _tn_task_activate(struct TN_Task *task); + +/** + * Should be called when task finishes waiting for anything. + * + * @param wait_rc return code that will be returned to waiting task + */ +static inline void _tn_task_wait_complete(struct TN_Task *task, enum TN_RCode wait_rc) +{ + _tn_task_clear_waiting(task, wait_rc); + + //-- if task isn't suspended, make it runnable + if (!_tn_task_is_suspended(task)){ + _tn_task_set_runnable(task); + } + +} + + +/** + * calls _tn_task_clear_runnable() for current task, i.e. tn_curr_run_task + * Set task state to TN_TASK_STATE_WAIT, set given wait_reason and timeout. + * + * If non-NULL wait_que is provided, then add task to it; otherwise reset task's task_queue. + * If timeout is not TN_WAIT_INFINITE, add task to tn_wait_timeout_list + */ +static inline void _tn_task_curr_to_wait_action( + struct TN_ListItem *wait_que, + enum TN_WaitReason wait_reason, + TN_Timeout timeout + ) +{ + _tn_task_clear_runnable(tn_curr_run_task); + _tn_task_set_waiting(tn_curr_run_task, wait_que, wait_reason, timeout); +} + + +/** + * Change priority of any task (runnable or non-runnable) + */ +void _tn_change_task_priority(struct TN_Task *task, int new_priority); + +/** + * When changing priority of the runnable task, this function + * should be called instead of plain assignment. + * + * For non-runnable tasks, this function should never be called. + * + * Remove current task from ready queue for its current priority, + * change its priority, add to the end of ready queue of new priority, + * find next task to run. + */ +void _tn_change_running_task_priority(struct TN_Task *task, int new_priority); + +#if 0 +#define _tn_task_set_last_rc(rc) { tn_curr_run_task = (rc); } + +/** + * If given return code is not `#TN_RC_OK`, save it in the task's structure + */ +void _tn_task_set_last_rc_if_error(enum TN_RCode rc); +#endif + +#if TN_USE_MUTEXES +/** + * Check if mutex is locked by task. + * + * @return TRUE if mutex is locked, FALSE otherwise. + */ +BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex); +#endif + +/** + * Wakes up first (if any) task from the queue, calling provided + * callback before. + * + * @param wait_queue + * Wait queue to get first task from + * @param wait_rc + * Code that will be returned to woken-up task as a result of waiting + * (this code is just given to `_tn_task_wait_complete()` actually) + * @param callback + * Callback function to call before wake task up, see + * `#_TN_CBBeforeTaskWaitComplete`. Can be `NULL`. + * @param user_data_1 + * Arbitrary data that is passed to the callback + * @param user_data_2 + * Arbitrary data that is passed to the callback + * + * + * @return + * - `TRUE` if queue is not empty and task has woken up + * - `FALSE` if queue is empty, so, no task to wake up + */ +BOOL _tn_task_first_wait_complete( + struct TN_ListItem *wait_queue, + enum TN_RCode wait_rc, + _TN_CBBeforeTaskWaitComplete *callback, + void *user_data_1, + void *user_data_2 + ); + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_TASKS_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_timer.h b/src/core/internal/_tn_timer.h new file mode 100644 index 0000000..c2780e7 --- /dev/null +++ b/src/core/internal/_tn_timer.h @@ -0,0 +1,154 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_TIMER_H +#define __TN_TIMER_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" + + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +/// +/// "generic" list of timers, for details, refer to \ref timers_implementation +extern struct TN_ListItem tn_timer_list__gen; +/// +/// "tick" lists of timers, for details, refer to \ref timers_implementation +extern struct TN_ListItem tn_timer_list__tick[ TN_TICK_LISTS_CNT ]; + + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +/** + * Should be called once at system startup (from `#tn_sys_start()`). + * It merely resets all timer lists. + */ +void _tn_timers_init(void); + +/** + * Should be called from $(TN_SYS_TIMER_LINK) interrupt. It performs all + * necessary timers housekeeping: moving them between lists, firing them, etc. + * + * See \ref timers_implementation for details. + */ +void _tn_timers_tick_proceed(void); + +/** + * Actual worker function that is called by `#tn_timer_start()`. + * Interrupts should be disabled when calling it. + */ +enum TN_RCode _tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout); + +/** + * Actual worker function that is called by `#tn_timer_cancel()`. + * Interrupts should be disabled when calling it. + */ +enum TN_RCode _tn_timer_cancel(struct TN_Timer *timer); + +/** + * Actual worker function that is called by `#tn_timer_create()`. + */ +enum TN_RCode _tn_timer_create( + struct TN_Timer *timer, + TN_TimerFunc *func, + void *p_user_data + ); + +/** + * Actual worker function that is called by `#tn_timer_set_func()`. + */ +enum TN_RCode _tn_timer_set_func( + struct TN_Timer *timer, + TN_TimerFunc *func, + void *p_user_data + ); + +/** + * Actual worker function that is called by `#tn_timer_is_active()`. + * Interrupts should be disabled when calling it. + */ +BOOL _tn_timer_is_active(struct TN_Timer *timer); + +/** + * Actual worker function that is called by `#tn_timer_time_left()`. + * Interrupts should be disabled when calling it. + */ +TN_Timeout _tn_timer_time_left(struct TN_Timer *timer); + + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_TIMER_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/tn_dqueue.c b/src/core/tn_dqueue.c index 15465fb..653ab73 100644 --- a/src/core/tn_dqueue.c +++ b/src/core/tn_dqueue.c @@ -41,7 +41,11 @@ #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_eventgrp.h" +#include "_tn_tasks.h" + #include "tn_dqueue.h" diff --git a/src/core/tn_eventgrp.c b/src/core/tn_eventgrp.c index deaaccb..d210324 100644 --- a/src/core/tn_eventgrp.c +++ b/src/core/tn_eventgrp.c @@ -40,7 +40,11 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_eventgrp.h" +#include "_tn_tasks.h" + //-- header of current module #include "tn_eventgrp.h" @@ -497,7 +501,7 @@ enum TN_RCode tn_eventgrp_imodify( ******************************************************************************/ /** - * See comments in the file tn_internal.h + * See comments in the file _tn_eventgrp.h */ enum TN_RCode _tn_eventgrp_link_set( struct TN_EGrpLink *eventgrp_link, @@ -524,7 +528,7 @@ enum TN_RCode _tn_eventgrp_link_set( /** - * See comments in the file tn_internal.h + * See comments in the file _tn_eventgrp.h */ enum TN_RCode _tn_eventgrp_link_reset( struct TN_EGrpLink *eventgrp_link @@ -540,7 +544,7 @@ enum TN_RCode _tn_eventgrp_link_reset( /** - * See comments in the file tn_internal.h + * See comments in the file _tn_eventgrp.h */ enum TN_RCode _tn_eventgrp_link_manage( struct TN_EGrpLink *eventgrp_link, diff --git a/src/core/tn_exch.c b/src/core/tn_exch.c index 1202893..20321c7 100644 --- a/src/core/tn_exch.c +++ b/src/core/tn_exch.c @@ -41,7 +41,10 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_exch.h" + //-- header of current module #include "tn_exch.h" @@ -268,7 +271,7 @@ enum TN_RCode tn_exch_read( ******************************************************************************/ /** - * See comments in the tn_internal.h file + * See comments in the _tn_exch.h file */ enum TN_RCode _tn_exch_write( struct TN_Exch *exch, @@ -283,7 +286,7 @@ enum TN_RCode _tn_exch_write( } /** - * See comments in the tn_internal.h file + * See comments in the _tn_exch.h file */ enum TN_RCode _tn_exch_read( struct TN_Exch *exch, diff --git a/src/core/tn_exch_link.c b/src/core/tn_exch_link.c index 4e5ee44..58ddcea 100644 --- a/src/core/tn_exch_link.c +++ b/src/core/tn_exch_link.c @@ -41,7 +41,10 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_exch_link.h" + //-- header of current module #include "tn_exch_link.h" @@ -147,7 +150,7 @@ static void _vtable_init() ******************************************************************************/ /** - * See comments in the tn_internal.h file + * See comments in the _tn_exch_link.h file */ const struct TN_ExchLink_VTable *_tn_exch_link_vtable(void) { @@ -157,7 +160,7 @@ const struct TN_ExchLink_VTable *_tn_exch_link_vtable(void) /** - * See comments in the tn_internal.h file + * See comments in the _tn_exch_link.h file */ enum TN_RCode _tn_exch_link_create( struct TN_ExchLink *exch_link @@ -181,7 +184,7 @@ enum TN_RCode _tn_exch_link_create( /** - * See comments in the tn_internal.h file + * See comments in the _tn_exch_link.h file */ enum TN_RCode _tn_exch_link_notify( struct TN_ExchLink *exch_link @@ -200,7 +203,7 @@ enum TN_RCode _tn_exch_link_notify( /** - * See comments in the tn_internal.h file + * See comments in the _tn_exch_link.h file */ enum TN_RCode _tn_exch_link_delete( struct TN_ExchLink *exch_link diff --git a/src/core/tn_fmem.c b/src/core/tn_fmem.c index d66cc42..189f432 100644 --- a/src/core/tn_fmem.c +++ b/src/core/tn_fmem.c @@ -42,7 +42,10 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_tasks.h" + //-- header of current module #include "tn_fmem.h" diff --git a/src/core/tn_internal.h b/src/core/tn_internal.h deleted file mode 100644 index d94c03e..0000000 --- a/src/core/tn_internal.h +++ /dev/null @@ -1,573 +0,0 @@ -/******************************************************************************* - * - * TNeoKernel: real-time kernel initially based on TNKernel - * - * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. - * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. - * TNeoKernel: copyright © 2014 Dmitry Frank. - * - * TNeoKernel was born as a thorough review and re-implementation of - * TNKernel. The new kernel has well-formed code, inherited bugs are fixed - * as well as new features being added, and it is tested carefully with - * unit-tests. - * - * API is changed somewhat, so it's not 100% compatible with TNKernel, - * hence the new name: TNeoKernel. - * - * Permission to use, copy, modify, and distribute this software in source - * and binary forms and its documentation for any purpose and without fee - * is hereby granted, provided that the above copyright notice appear - * in all copies and that both that copyright notice and this permission - * notice appear in supporting documentation. - * - * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - ******************************************************************************/ - -/** - * \file - * - * Internal TNeoKernel header, should not be included by the application. - */ - - -#ifndef _TN_INTERNAL_H -#define _TN_INTERNAL_H - - -/******************************************************************************* - * INCLUDED FILES - ******************************************************************************/ - -#include "tn_arch.h" - -#include "tn_tasks.h" //-- for inline functions -#include "tn_sys.h" //-- for inline functions - - - - -#ifdef __cplusplus -extern "C" { /*}*/ -#endif - -/******************************************************************************* - * EXTERNAL TYPES - ******************************************************************************/ - -struct TN_Mutex; -struct TN_ListItem; -struct TN_Timer; -struct TN_Exch; -struct TN_ExchLink; - - - -/******************************************************************************* - * GLOBAL VARIABLES - ******************************************************************************/ - -/// list of all ready to run (TN_TASK_STATE_RUNNABLE) tasks -extern struct TN_ListItem tn_ready_list[TN_PRIORITIES_CNT]; - -/// list all created tasks (now it is used for statictic only) -extern struct TN_ListItem tn_create_queue; - -/// count of created tasks -extern volatile int tn_created_tasks_cnt; - -/// system state flags -extern volatile enum TN_StateFlag tn_sys_state; - -/// task that runs now -extern struct TN_Task *tn_curr_run_task; - -/// task that should run as soon as possible (after context switch) -extern struct TN_Task *tn_next_task_to_run; - -/// bitmask of priorities with runnable tasks. -/// lowest priority bit (1 << (TN_PRIORITIES_CNT - 1)) should always be set, -/// since this priority is used by idle task and it is always runnable. -extern volatile unsigned int tn_ready_to_run_bmp; - -/// system time that is get/set by `tn_sys_time_get()`, -/// respectively. -extern volatile unsigned int tn_sys_time_count; - -/// current interrupt nesting count. Used by macros -/// `tn_soft_isr()` and `tn_srs_isr()`. -extern volatile int tn_int_nest_count; - -/// saved task stack pointer. Needed when switching stack pointer from -/// task stack to interrupt stack. -extern void *tn_user_sp; - -/// saved ISR stack pointer. Needed when switching stack pointer from -/// interrupt stack to task stack. -extern void *tn_int_sp; - -/// -/// idle task structure -extern struct TN_Task tn_idle_task; - - -/******************************************************************************* - * INTERNAL KERNEL TYPES - ******************************************************************************/ - -/* none yet */ - - - - -/******************************************************************************* - * DEFINITIONS - ******************************************************************************/ - -#if !defined(container_of) -/* given a pointer @ptr to the field @member embedded into type (usually - * struct) @type, return pointer to the embedding instance of @type. */ -#define container_of(ptr, type, member) \ - ((type *)((char *)(ptr)-(char *)(&((type *)0)->member))) -#endif - - -#ifndef TN_DEBUG -# error TN_DEBUG is not defined -#endif - -#if TN_DEBUG -#define _TN_BUG_ON(cond, ...){ \ - if (cond){ \ - _TN_FATAL_ERROR(__VA_ARGS__); \ - } \ -} -#else -#define _TN_BUG_ON(cond) /* nothing */ -#endif - - - -/******************************************************************************* - * tn_sys.c - ******************************************************************************/ - -/** - * Remove all tasks from wait queue, returning the TN_RC_DELETED code. - */ -void _tn_wait_queue_notify_deleted(struct TN_ListItem *wait_queue); - - -/** - * Set flags by bitmask. - * Given flags value will be OR-ed with existing flags. - * - * @return previous tn_sys_state value. - */ -enum TN_StateFlag _tn_sys_state_flags_set(enum TN_StateFlag flags); - -/** - * Clear flags by bitmask - * Given flags value will be inverted and AND-ed with existing flags. - * - * @return previous tn_sys_state value. - */ -enum TN_StateFlag _tn_sys_state_flags_clear(enum TN_StateFlag flags); - -#if TN_MUTEX_DEADLOCK_DETECT -void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task); -#endif - -static inline BOOL _tn_need_context_switch(void) -{ - return (tn_curr_run_task != tn_next_task_to_run); -} - -static inline void _tn_context_switch_pend_if_needed(void) -{ - if (_tn_need_context_switch()){ - _tn_arch_context_switch_pend(); - } -} - - - - - -/******************************************************************************* - * tn_tasks.c - ******************************************************************************/ - -/** - * Callback that is given to `_tn_task_first_wait_complete()`, may perform - * any needed actions before waking task up, e.g. set some data in the `struct - * TN_Task` that task is waiting for. - * - * @param task - * Task that is going to be waken up - * @param user_data_1 - * Arbitrary user data given to `_tn_task_first_wait_complete()` - * @param user_data_2 - * Arbitrary user data given to `_tn_task_first_wait_complete()` - */ -typedef void (_TN_CBBeforeTaskWaitComplete)( - struct TN_Task *task, - void *user_data_1, - void *user_data_2 - ); - - -static inline BOOL _tn_task_is_runnable(struct TN_Task *task) -{ - return !!(task->task_state & TN_TASK_STATE_RUNNABLE); -} - -static inline BOOL _tn_task_is_waiting(struct TN_Task *task) -{ - return !!(task->task_state & TN_TASK_STATE_WAIT); -} - -static inline BOOL _tn_task_is_suspended(struct TN_Task *task) -{ - return !!(task->task_state & TN_TASK_STATE_SUSPEND); -} - -static inline BOOL _tn_task_is_dormant(struct TN_Task *task) -{ - return !!(task->task_state & TN_TASK_STATE_DORMANT); -} - -/** - * Should be called when task_state is NONE. - * - * Set RUNNABLE bit in task_state, - * put task on the 'ready queue' for its priority, - * - * if priority is higher than tn_next_task_to_run's priority, - * then set tn_next_task_to_run to this task and return TRUE, - * otherwise return FALSE. - */ -void _tn_task_set_runnable(struct TN_Task *task); - - -/** - * Should be called when task_state has just single RUNNABLE bit set. - * - * Clear RUNNABLE bit, remove task from 'ready queue', determine and set - * new tn_next_task_to_run. - */ -void _tn_task_clear_runnable(struct TN_Task *task); - -void _tn_task_set_waiting( - struct TN_Task *task, - struct TN_ListItem *wait_que, - enum TN_WaitReason wait_reason, - TN_Timeout timeout - ); - -/** - * @param wait_rc return code that will be returned to waiting task - */ -void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc); - -void _tn_task_set_suspended(struct TN_Task *task); -void _tn_task_clear_suspended(struct TN_Task *task); - -void _tn_task_set_dormant(struct TN_Task* task); - -void _tn_task_clear_dormant(struct TN_Task *task); - -enum TN_RCode _tn_task_activate(struct TN_Task *task); - -/** - * Should be called when task finishes waiting for anything. - * - * @param wait_rc return code that will be returned to waiting task - */ -static inline void _tn_task_wait_complete(struct TN_Task *task, enum TN_RCode wait_rc) -{ - _tn_task_clear_waiting(task, wait_rc); - - //-- if task isn't suspended, make it runnable - if (!_tn_task_is_suspended(task)){ - _tn_task_set_runnable(task); - } - -} - - -/** - * calls _tn_task_clear_runnable() for current task, i.e. tn_curr_run_task - * Set task state to TN_TASK_STATE_WAIT, set given wait_reason and timeout. - * - * If non-NULL wait_que is provided, then add task to it; otherwise reset task's task_queue. - * If timeout is not TN_WAIT_INFINITE, add task to tn_wait_timeout_list - */ -static inline void _tn_task_curr_to_wait_action( - struct TN_ListItem *wait_que, - enum TN_WaitReason wait_reason, - TN_Timeout timeout - ) -{ - _tn_task_clear_runnable(tn_curr_run_task); - _tn_task_set_waiting(tn_curr_run_task, wait_que, wait_reason, timeout); -} - - -/** - * Change priority of any task (runnable or non-runnable) - */ -void _tn_change_task_priority(struct TN_Task *task, int new_priority); - -/** - * When changing priority of the runnable task, this function - * should be called instead of plain assignment. - * - * For non-runnable tasks, this function should never be called. - * - * Remove current task from ready queue for its current priority, - * change its priority, add to the end of ready queue of new priority, - * find next task to run. - */ -void _tn_change_running_task_priority(struct TN_Task *task, int new_priority); - -#if 0 -#define _tn_task_set_last_rc(rc) { tn_curr_run_task = (rc); } - -/** - * If given return code is not `#TN_RC_OK`, save it in the task's structure - */ -void _tn_task_set_last_rc_if_error(enum TN_RCode rc); -#endif - -#if TN_USE_MUTEXES -/** - * Check if mutex is locked by task. - * - * @return TRUE if mutex is locked, FALSE otherwise. - */ -BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex); -#endif - -/** - * Wakes up first (if any) task from the queue, calling provided - * callback before. - * - * @param wait_queue - * Wait queue to get first task from - * @param wait_rc - * Code that will be returned to woken-up task as a result of waiting - * (this code is just given to `_tn_task_wait_complete()` actually) - * @param callback - * Callback function to call before wake task up, see - * `#_TN_CBBeforeTaskWaitComplete`. Can be `NULL`. - * @param user_data_1 - * Arbitrary data that is passed to the callback - * @param user_data_2 - * Arbitrary data that is passed to the callback - * - * - * @return - * - `TRUE` if queue is not empty and task has woken up - * - `FALSE` if queue is empty, so, no task to wake up - */ -BOOL _tn_task_first_wait_complete( - struct TN_ListItem *wait_queue, - enum TN_RCode wait_rc, - _TN_CBBeforeTaskWaitComplete *callback, - void *user_data_1, - void *user_data_2 - ); - - - - -#define _tn_get_task_by_tsk_queue(que) \ - (que ? container_of(que, struct TN_Task, task_queue) : 0) - - - -/******************************************************************************* - * tn_mutex.c - ******************************************************************************/ - -#if TN_USE_MUTEXES -/** - * Unlock all mutexes locked by the task - */ -void _tn_mutex_unlock_all_by_task(struct TN_Task *task); - -/** - * Should be called when task finishes waiting - * for mutex with priority inheritance - */ -void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task); - -/** - * Should be called when task winishes waiting - * for any mutex (no matter which algorithm it uses) - */ -void _tn_mutex_on_task_wait_complete(struct TN_Task *task); - -#else -static inline void _tn_mutex_unlock_all_by_task(struct TN_Task *task) {} -static inline void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task) {} -static inline void _tn_mutex_on_task_wait_complete(struct TN_Task *task) {} -#endif - - - - -/******************************************************************************* - * tn_timer.c - ******************************************************************************/ - -/// -/// "generic" list of timers, for details, refer to \ref timers_implementation -extern struct TN_ListItem tn_timer_list__gen; -/// -/// "tick" lists of timers, for details, refer to \ref timers_implementation -extern struct TN_ListItem tn_timer_list__tick[ TN_TICK_LISTS_CNT ]; - - - - -/** - * Should be called once at system startup (from `#tn_sys_start()`). - * It merely resets all timer lists. - */ -void _tn_timers_init(void); - -/** - * Should be called from $(TN_SYS_TIMER_LINK) interrupt. It performs all - * necessary timers housekeeping: moving them between lists, firing them, etc. - * - * See \ref timers_implementation for details. - */ -void _tn_timers_tick_proceed(void); - -/** - * Actual worker function that is called by `#tn_timer_start()`. - * Interrupts should be disabled when calling it. - */ -enum TN_RCode _tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout); - -/** - * Actual worker function that is called by `#tn_timer_cancel()`. - * Interrupts should be disabled when calling it. - */ -enum TN_RCode _tn_timer_cancel(struct TN_Timer *timer); - -/** - * Actual worker function that is called by `#tn_timer_create()`. - */ -enum TN_RCode _tn_timer_create( - struct TN_Timer *timer, - TN_TimerFunc *func, - void *p_user_data - ); - -/** - * Actual worker function that is called by `#tn_timer_set_func()`. - */ -enum TN_RCode _tn_timer_set_func( - struct TN_Timer *timer, - TN_TimerFunc *func, - void *p_user_data - ); - -/** - * Actual worker function that is called by `#tn_timer_is_active()`. - * Interrupts should be disabled when calling it. - */ -BOOL _tn_timer_is_active(struct TN_Timer *timer); - -/** - * Actual worker function that is called by `#tn_timer_time_left()`. - * Interrupts should be disabled when calling it. - */ -TN_Timeout _tn_timer_time_left(struct TN_Timer *timer); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - - -/******************************************************************************* - * tn_eventgrp.c - ******************************************************************************/ - -/** - * Establish link to the event group - */ -enum TN_RCode _tn_eventgrp_link_set( - struct TN_EGrpLink *eventgrp_link, - struct TN_EventGrp *eventgrp, - TN_UWord pattern - ); - -/** - * Reset link to the event group (no matter whether it is already established) - */ -enum TN_RCode _tn_eventgrp_link_reset( - struct TN_EGrpLink *eventgrp_link - ); - -enum TN_RCode _tn_eventgrp_link_manage( - struct TN_EGrpLink *eventgrp_link, - BOOL set - ); - - - - -/******************************************************************************* - * tn_exch.c - ******************************************************************************/ - -enum TN_RCode _tn_exch_write( - struct TN_Exch *exch, - const void *data - ); - -enum TN_RCode _tn_exch_read( - struct TN_Exch *exch, - void *data_tgt - ); - - - -/******************************************************************************* - * tn_exch_link.c - ******************************************************************************/ - -const struct TN_ExchLink_VTable *_tn_exch_link_vtable(void); - -enum TN_RCode _tn_exch_link_create( - struct TN_ExchLink *exch_link - ); - -enum TN_RCode _tn_exch_link_notify( - struct TN_ExchLink *exch_link - ); - -enum TN_RCode _tn_exch_link_delete( - struct TN_ExchLink *exch_link - ); - - - -#endif // _TN_INTERNAL_H - - diff --git a/src/core/tn_mutex.c b/src/core/tn_mutex.c index 4fe1836..80b60b5 100644 --- a/src/core/tn_mutex.c +++ b/src/core/tn_mutex.c @@ -41,7 +41,10 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_mutex.h" +#include "_tn_tasks.h" //-- header of current module #include "tn_mutex.h" @@ -782,7 +785,7 @@ enum TN_RCode tn_mutex_unlock(struct TN_Mutex *mutex) ******************************************************************************/ /** - * See comment in tn_internal.h file + * See comment in _tn_mutex.h file */ void _tn_mutex_unlock_all_by_task(struct TN_Task *task) { @@ -803,7 +806,7 @@ void _tn_mutex_unlock_all_by_task(struct TN_Task *task) /** - * See comments in tn_internal.h file + * See comments in _tn_mutex.h file */ void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task) { @@ -849,7 +852,7 @@ void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task) } /** - * See comments in tn_internal.h file + * See comments in _tn_mutex.h file */ void _tn_mutex_on_task_wait_complete(struct TN_Task *task) { diff --git a/src/core/tn_sem.c b/src/core/tn_sem.c index 8f43d42..6ab68ec 100644 --- a/src/core/tn_sem.c +++ b/src/core/tn_sem.c @@ -42,7 +42,10 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_tasks.h" + //-- header of current module #include "tn_sem.h" diff --git a/src/core/tn_sys.c b/src/core/tn_sys.c index cec854a..dcf4fa2 100644 --- a/src/core/tn_sys.c +++ b/src/core/tn_sys.c @@ -48,7 +48,12 @@ #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_sys.h" +#include "_tn_timer.h" +#include "_tn_tasks.h" + #include "tn_tasks.h" #include "tn_timer.h" @@ -61,7 +66,7 @@ ******************************************************************************/ /* - * For comments on these variables, please see tn_internal.h file. + * For comments on these variables, please see _tn_sys.h file. */ struct TN_ListItem tn_ready_list[TN_PRIORITIES_CNT]; struct TN_ListItem tn_create_queue; @@ -408,7 +413,7 @@ TN_TaskBody *tn_cur_task_body_get(void) ******************************************************************************/ /** - * See comment in the tn_internal.h file + * See comment in the _tn_sys.h file */ void _tn_wait_queue_notify_deleted(struct TN_ListItem *wait_queue) { diff --git a/src/core/tn_tasks.c b/src/core/tn_tasks.c index 714cccd..5584c6e 100644 --- a/src/core/tn_tasks.c +++ b/src/core/tn_tasks.c @@ -41,7 +41,12 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_tasks.h" +#include "_tn_mutex.h" +#include "_tn_timer.h" + //-- header of current module #include "tn_tasks.h" @@ -789,7 +794,7 @@ enum TN_RCode tn_task_change_priority(struct TN_Task *task, int new_priority) ******************************************************************************/ /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ void _tn_task_set_runnable(struct TN_Task * task) { @@ -819,7 +824,7 @@ void _tn_task_set_runnable(struct TN_Task * task) } /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ void _tn_task_clear_runnable(struct TN_Task *task) { @@ -911,7 +916,7 @@ void _tn_task_set_waiting( } /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc) { @@ -1048,7 +1053,7 @@ enum TN_RCode _tn_task_activate(struct TN_Task *task) } /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ BOOL _tn_task_first_wait_complete( struct TN_ListItem *wait_queue, @@ -1084,7 +1089,7 @@ BOOL _tn_task_first_wait_complete( /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ void _tn_change_task_priority(struct TN_Task *task, int new_priority) { @@ -1096,7 +1101,7 @@ void _tn_change_task_priority(struct TN_Task *task, int new_priority) } /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ void _tn_change_running_task_priority(struct TN_Task *task, int new_priority) { @@ -1117,7 +1122,7 @@ void _tn_change_running_task_priority(struct TN_Task *task, int new_priority) #if 0 /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ void _tn_task_set_last_rc_if_error(enum TN_RCode rc) { @@ -1133,7 +1138,7 @@ void _tn_task_set_last_rc_if_error(enum TN_RCode rc) #if TN_USE_MUTEXES /** - * See comment in the tn_internal.h file + * See comment in the _tn_tasks.h file */ BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex) { diff --git a/src/core/tn_timer.c b/src/core/tn_timer.c index e79da5a..7693fac 100644 --- a/src/core/tn_timer.c +++ b/src/core/tn_timer.c @@ -41,7 +41,10 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" -#include "tn_internal.h" + +//-- internal tnkernel headers +#include "_tn_timer.h" + //-- header of current module #include "tn_timer.h" @@ -277,7 +280,7 @@ enum TN_RCode tn_timer_time_left( ******************************************************************************/ /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ void _tn_timers_init(void) { @@ -293,7 +296,7 @@ void _tn_timers_init(void) } /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ void _tn_timers_tick_proceed(void) { @@ -397,7 +400,7 @@ void _tn_timers_tick_proceed(void) } /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ enum TN_RCode _tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout) { @@ -439,7 +442,7 @@ enum TN_RCode _tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout) } /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ enum TN_RCode _tn_timer_cancel(struct TN_Timer *timer) { @@ -467,7 +470,7 @@ enum TN_RCode _tn_timer_cancel(struct TN_Timer *timer) } /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ enum TN_RCode _tn_timer_create( struct TN_Timer *timer, @@ -491,7 +494,7 @@ enum TN_RCode _tn_timer_create( } /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ enum TN_RCode _tn_timer_set_func( struct TN_Timer *timer, @@ -512,7 +515,7 @@ enum TN_RCode _tn_timer_set_func( } /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ BOOL _tn_timer_is_active(struct TN_Timer *timer) { @@ -527,7 +530,7 @@ BOOL _tn_timer_is_active(struct TN_Timer *timer) } /** - * See comments in the tn_internal.h file. + * See comments in the _tn_timer.h file. */ TN_Timeout _tn_timer_time_left(struct TN_Timer *timer) { diff --git a/stuff/doxygen/tn_doxyfile b/stuff/doxygen/tn_doxyfile index cadbdb3..21723da 100644 --- a/stuff/doxygen/tn_doxyfile +++ b/stuff/doxygen/tn_doxyfile @@ -807,8 +807,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../../src/core/tn_internal.h \ - ../../src/core/tn_list.h \ +EXCLUDE = ../../src/core/tn_list.h \ ../../src/tn_cfg.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or @@ -825,7 +824,10 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +# by dfrank: internal kernel headers start with "_tn_...", so, exclude them + +EXCLUDE_PATTERNS = */_tn_* + # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the From 6975134f1c8330ddb1d8c626efa2f2d3dd60c188 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Wed, 22 Oct 2014 17:52:56 +0400 Subject: [PATCH 08/96] working on tn_exch; added tn_exch_link_queue --- src/arch/example/tn_arch_example.h | 6 + src/arch/pic32/tn_arch_pic32.h | 7 + .../tneokernel.X/nbproject/configurations.xml | 1 + src/core/internal/_tn_dqueue.h | 101 ++++++++ src/core/internal/_tn_exch.h | 2 +- src/core/internal/_tn_fmem.h | 101 ++++++++ src/core/internal/_tn_sys.h | 4 +- src/core/tn_dqueue.c | 5 +- src/core/tn_exch.c | 94 ++++---- src/core/tn_exch.h | 2 + src/core/tn_exch_link.c | 42 +++- src/core/tn_exch_link.h | 15 +- src/core/tn_exch_link_queue.c | 221 ++++++++++++++++++ src/core/tn_exch_link_queue.h | 132 +++++++++++ src/core/tn_fmem.c | 7 +- src/core/tn_sys.c | 14 ++ stuff/vimwiki/index.wiki | 24 +- 17 files changed, 708 insertions(+), 70 deletions(-) create mode 100644 src/core/internal/_tn_dqueue.h create mode 100644 src/core/internal/_tn_fmem.h create mode 100644 src/core/tn_exch_link_queue.c create mode 100644 src/core/tn_exch_link_queue.h diff --git a/src/arch/example/tn_arch_example.h b/src/arch/example/tn_arch_example.h index f0960e8..b44db7e 100644 --- a/src/arch/example/tn_arch_example.h +++ b/src/arch/example/tn_arch_example.h @@ -196,5 +196,11 @@ typedef unsigned int TN_UWord; _tn_context_switch_pend_if_needed() +/** + * Converts size in bytes to size in `#TN_UWord`. + * For 32-bit platforms, we should shift it by 2 bit to the right; + * for 16-bit platforms, we should shift it by 1 bit to the right. + */ +#define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 2) #endif // _TN_ARCH_EXAMPLE_H diff --git a/src/arch/pic32/tn_arch_pic32.h b/src/arch/pic32/tn_arch_pic32.h index 4623517..94c7237 100644 --- a/src/arch/pic32/tn_arch_pic32.h +++ b/src/arch/pic32/tn_arch_pic32.h @@ -249,6 +249,13 @@ typedef unsigned int TN_UWord; #define _TN_CONTEXT_SWITCH_IPEND_IF_NEEDED() \ _tn_context_switch_pend_if_needed() +/** + * Converts size in bytes to size in `#TN_UWord`. + * For 32-bit platforms, we should shift it by 2 bit to the right; + * for 16-bit platforms, we should shift it by 1 bit to the right. + */ +#define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 2) + #endif //-- DOXYGEN_SHOULD_SKIP_THIS diff --git a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml index 49d1758..9877bc2 100644 --- a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml +++ b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml @@ -29,6 +29,7 @@ ../../../core/tn_fmem.c ../../../core/tn_timer.c ../../../core/tn_exch.c + ../../../core/tn_exch_link_queue.c id_dque == TN_ID_DATAQUEUE); +} + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_DQUEUE_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_exch.h b/src/core/internal/_tn_exch.h index 9777f88..c779ef0 100644 --- a/src/core/internal/_tn_exch.h +++ b/src/core/internal/_tn_exch.h @@ -76,7 +76,7 @@ struct TN_Exch; * PROTECTED FUNCTION PROTOTYPES ******************************************************************************/ -enum TN_RCode _tn_exch_write( +void _tn_exch_write( struct TN_Exch *exch, const void *data ); diff --git a/src/core/internal/_tn_fmem.h b/src/core/internal/_tn_fmem.h new file mode 100644 index 0000000..0a09dd2 --- /dev/null +++ b/src/core/internal/_tn_fmem.h @@ -0,0 +1,101 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_FMEM_H +#define __TN_FMEM_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" +#include "tn_dqueue.h" + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * EXTERNAL TYPES + ******************************************************************************/ + +struct TN_Exch; + + + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_fmem_is_valid( + struct TN_FMem *fmem + ) +{ + return (fmem->id_fmp == TN_ID_FSMEMORYPOOL); +} + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_FMEM_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/internal/_tn_sys.h b/src/core/internal/_tn_sys.h index f147a19..cb4041b 100644 --- a/src/core/internal/_tn_sys.h +++ b/src/core/internal/_tn_sys.h @@ -178,7 +178,9 @@ static inline void _tn_context_switch_pend_if_needed(void) } } - +void _tn_memcpy_uword( + TN_UWord *tgt, const TN_UWord *src, unsigned int size_uwords + ); #ifdef __cplusplus diff --git a/src/core/tn_dqueue.c b/src/core/tn_dqueue.c index 653ab73..d31c485 100644 --- a/src/core/tn_dqueue.c +++ b/src/core/tn_dqueue.c @@ -48,6 +48,7 @@ #include "tn_dqueue.h" +#include "_tn_dqueue.h" #include "tn_tasks.h" @@ -79,7 +80,7 @@ static inline enum TN_RCode _check_param_generic( if (dque == NULL){ rc = TN_RC_WPARAM; - } else if (dque->id_dque != TN_ID_DATAQUEUE){ + } else if (!_tn_dqueue_is_valid(dque)){ rc = TN_RC_INVALID_OBJ; } @@ -96,7 +97,7 @@ static inline enum TN_RCode _check_param_create( if (dque == NULL){ rc = TN_RC_WPARAM; - } else if (items_cnt < 0 || dque->id_dque == TN_ID_DATAQUEUE){ + } else if (items_cnt < 0 || _tn_dqueue_is_valid(dque)){ rc = TN_RC_WPARAM; } diff --git a/src/core/tn_exch.c b/src/core/tn_exch.c index 20321c7..a718cd3 100644 --- a/src/core/tn_exch.c +++ b/src/core/tn_exch.c @@ -41,9 +41,12 @@ //-- common tnkernel headers #include "tn_common.h" #include "tn_sys.h" +#include "tn_exch_link.h" //-- internal tnkernel headers +#include "_tn_sys.h" #include "_tn_exch.h" +#include "_tn_exch_link.h" //-- header of current module @@ -110,26 +113,19 @@ static inline enum TN_RCode _check_param_create( #endif // }}} -/** - * @param size size in bytes - */ -void _memcpy_uword(TN_UWord *tgt, const TN_UWord *src, unsigned int size) -{ - //TODO: optimize - int uwords_cnt = size / sizeof(TN_UWord); - int i; - for (i = 0; i < uwords_cnt; i++){ - *tgt++ = *src++; - } -} - -enum TN_RCode _notify_all( +static enum TN_RCode _notify_all( struct TN_Exch *exch ) { enum TN_RCode rc = TN_RC_OK; - - //TODO + struct TN_ExchLink *exch_link; + + tn_list_for_each_entry(exch_link, &(exch->links_list), links_list_item){ + rc = _tn_exch_link_notify(exch_link); + if (rc != TN_RC_OK){ + break; + } + } return rc; } @@ -202,61 +198,62 @@ enum TN_RCode tn_exch_create( enum TN_RCode tn_exch_delete(struct TN_Exch *exch) { enum TN_RCode rc = _check_param_generic(exch); + int sr_saved; if (rc != TN_RC_OK){ //-- just return rc as it is - } else if (!tn_is_task_context()){ - rc = TN_RC_WCONTEXT; } else { - TN_INTSAVE_DATA; - - TN_INT_DIS_SAVE(); + sr_saved = tn_arch_sr_save_int_dis(); exch->id_exch = 0; //-- Exchange object does not exist now - TN_INT_RESTORE(); + tn_arch_sr_restore(sr_saved); } return rc; } -enum TN_RCode tn_exch_write( +/** + * See comments in the header file (tn_exch.h) + */ +enum TN_RCode tn_exch_read( struct TN_Exch *exch, - const void *data + void *data_tgt ) { + int sr_saved; enum TN_RCode rc = _check_param_generic(exch); if (rc != TN_RC_OK){ //-- just return rc as it is - } else if (!tn_is_task_context()){ - rc = TN_RC_WCONTEXT; } else { - TN_INTSAVE_DATA; - - TN_INT_DIS_SAVE(); - rc =_tn_exch_write(exch, data); - TN_INT_RESTORE(); + sr_saved = tn_arch_sr_save_int_dis(); + rc = _tn_exch_read(exch, data_tgt); + tn_arch_sr_restore(sr_saved); } return rc; } -enum TN_RCode tn_exch_read( + +/** + * See comments in the header file (tn_exch.h) + */ +enum TN_RCode tn_exch_write( struct TN_Exch *exch, - void *data_tgt + const void *data ) { enum TN_RCode rc = _check_param_generic(exch); + int sr_saved; if (rc != TN_RC_OK){ //-- just return rc as it is - } else if (!tn_is_task_context()){ - rc = TN_RC_WCONTEXT; } else { - TN_INTSAVE_DATA; + sr_saved = tn_arch_sr_save_int_dis(); - TN_INT_DIS_SAVE(); - rc = _tn_exch_read(exch, data_tgt); - TN_INT_RESTORE(); + _tn_exch_write(exch, data); + rc = _notify_all(exch); + + tn_arch_sr_restore(sr_saved); } return rc; @@ -273,18 +270,19 @@ enum TN_RCode tn_exch_read( /** * See comments in the _tn_exch.h file */ -enum TN_RCode _tn_exch_write( +void _tn_exch_write( struct TN_Exch *exch, const void *data ) { - _memcpy_uword((TN_UWord *)exch->data, (const TN_UWord *)data, exch->size); - - _notify_all(exch); - - return TN_RC_OK; + _tn_memcpy_uword( + (TN_UWord *)exch->data, + (const TN_UWord *)data, + _TN_SIZE_BYTES_TO_UWORDS(exch->size) + ); } + /** * See comments in the _tn_exch.h file */ @@ -293,7 +291,11 @@ enum TN_RCode _tn_exch_read( void *data_tgt ) { - _memcpy_uword((TN_UWord *)data_tgt, (const TN_UWord *)exch->data, exch->size); + _tn_memcpy_uword( + (TN_UWord *)data_tgt, + (const TN_UWord *)exch->data, + _TN_SIZE_BYTES_TO_UWORDS(exch->size) + ); return TN_RC_OK; } diff --git a/src/core/tn_exch.h b/src/core/tn_exch.h index 80f1e77..a768849 100644 --- a/src/core/tn_exch.h +++ b/src/core/tn_exch.h @@ -102,6 +102,7 @@ struct TN_Exch { enum TN_ObjId id_exch; }; +#if 0 struct TN_ExchLinkQueue { /// /// A list item to be included in the exchange links list @@ -145,6 +146,7 @@ struct TN_ExchLinkCallback { /// User data to be given to callback function void *p_user_data; }; +#endif /******************************************************************************* diff --git a/src/core/tn_exch_link.c b/src/core/tn_exch_link.c index 58ddcea..3c09c9e 100644 --- a/src/core/tn_exch_link.c +++ b/src/core/tn_exch_link.c @@ -56,12 +56,27 @@ ******************************************************************************/ +/******************************************************************************* + * PRIVATE FUNCTION PROTOTYPES + ******************************************************************************/ + +static enum TN_RCode _notify_error(struct TN_ExchLink *exch_link); +static enum TN_RCode _dtor(struct TN_ExchLink *exch_link); + + + /******************************************************************************* * PRIVATE DATA ******************************************************************************/ -static struct TN_ExchLink_VTable _vtable = {}; -static BOOL _vtable_initialized = FALSE; +/** + * Virtual methods table of "abstract class" `#TN_ExchLink`. + */ +static const struct TN_ExchLink_VTable _vtable = { + .notify = _notify_error, + .dtor = _dtor, +}; +//static BOOL _vtable_initialized = FALSE; @@ -116,7 +131,7 @@ static inline enum TN_RCode _check_param_create( #endif // }}} -static enum TN_RCode _notify(struct TN_ExchLink *exch_link) +static enum TN_RCode _notify_error(struct TN_ExchLink *exch_link) { //-- should never be here _TN_FATAL_ERROR("called notify() of base TN_ExchLink"); @@ -125,19 +140,21 @@ static enum TN_RCode _notify(struct TN_ExchLink *exch_link) static enum TN_RCode _dtor(struct TN_ExchLink *exch_link) { - //-- nothing to do here + exch_link->id_exch_link = 0; //-- exchange link does not exist now return TN_RC_OK; } +#if 0 static void _vtable_init() { if (!_vtable_initialized){ - _vtable.notify = _notify; + _vtable.notify = _notify_error; _vtable.dtor = _dtor; _vtable_initialized = TRUE; } } +#endif @@ -154,7 +171,7 @@ static void _vtable_init() */ const struct TN_ExchLink_VTable *_tn_exch_link_vtable(void) { - _vtable_init(); + //_vtable_init(); return &_vtable; } @@ -171,7 +188,7 @@ enum TN_RCode _tn_exch_link_create( if (rc != TN_RC_OK){ //-- just return rc as it is } else { - _vtable_init(); + //_vtable_init(); exch_link->vtable = &_vtable; tn_list_reset(&(exch_link->links_list_item)); @@ -202,6 +219,7 @@ enum TN_RCode _tn_exch_link_notify( } + /** * See comments in the _tn_exch_link.h file */ @@ -209,7 +227,15 @@ enum TN_RCode _tn_exch_link_delete( struct TN_ExchLink *exch_link ) { - return exch_link->vtable->dtor(exch_link); + enum TN_RCode rc = _check_param_generic(exch_link); + + if (rc != TN_RC_OK){ + //-- just return rc as it is + } else { + rc = exch_link->vtable->dtor(exch_link); + } + + return rc; } diff --git a/src/core/tn_exch_link.h b/src/core/tn_exch_link.h index 01d59f7..0264984 100644 --- a/src/core/tn_exch_link.h +++ b/src/core/tn_exch_link.h @@ -37,7 +37,10 @@ /** * \file * - * Exchange link (base structure). For internal kernel usage only. + * Exchange link (in terms of OOP, it's an "abstract class" of any exchange + * link). + * + * For internal kernel usage only. * */ @@ -99,10 +102,14 @@ struct TN_ExchLink { /// A list item to be included in the exchange links list struct TN_ListItem links_list_item; /// - /// Virtual methods table - struct TN_ExchLink_VTable *vtable; + /// Pointer to `#TN_Exch` object to which this link is added. + /// If not added to any exchange object, it is `NULL`. + struct TN_Exch *exch; + /// + /// Pointer to the virtual methods table + const struct TN_ExchLink_VTable *vtable; /// - /// id for object validity verification + /// Id for object validity verification enum TN_ObjId id_exch_link; }; diff --git a/src/core/tn_exch_link_queue.c b/src/core/tn_exch_link_queue.c new file mode 100644 index 0000000..dc0934e --- /dev/null +++ b/src/core/tn_exch_link_queue.c @@ -0,0 +1,221 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +//-- common tnkernel headers +#include "tn_common.h" +#include "tn_sys.h" + +#include "tn_exch.h" + +//-- internal tnkernel headers +#include "_tn_exch_link.h" +#include "_tn_dqueue.h" +#include "_tn_fmem.h" + + +//-- header of current module +#include "tn_exch_link_queue.h" + + + +/******************************************************************************* + * PUBLIC DATA + ******************************************************************************/ + + +/******************************************************************************* + * PRIVATE FUNCTION PROTOTYPES + ******************************************************************************/ + +static enum TN_RCode _notify(struct TN_ExchLink *exch_link); +static enum TN_RCode _dtor(struct TN_ExchLink *exch_link); + + + +/******************************************************************************* + * PRIVATE DATA + ******************************************************************************/ + +/** + * Virtual methods table + */ +static const struct TN_ExchLink_VTable _vtable = { + .notify = _notify, + .dtor = _dtor, +}; + + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +#define _tn_get_exch_link_queue_by_exch_link(exch_link) \ + (exch_link ? container_of(exch_link, struct TN_ExchLinkQueue, super) : 0) + + + + + +/******************************************************************************* + * PRIVATE FUNCTIONS + ******************************************************************************/ + +//-- Additional param checking {{{ +#if TN_CHECK_PARAM +static inline enum TN_RCode _check_param_create( + struct TN_ExchLinkQueue *exch_link_queue, + struct TN_DQueue *queue, + struct TN_FMem *fmem + ) +{ + enum TN_RCode rc = TN_RC_OK; + + if (exch_link_queue == NULL){ + rc = TN_RC_WPARAM; + } else if (!_tn_dqueue_is_valid(queue)){ + rc = TN_RC_WPARAM; + } else if (!_tn_fmem_is_valid(fmem)){ + rc = TN_RC_WPARAM; + } + + return rc; +} + +#else +# define _check_param_create(exch_link) (TN_RC_OK) +#endif +// }}} + + +static enum TN_RCode _notify(struct TN_ExchLink *exch_link) +{ + enum TN_RCode rc = TN_RC_OK; + + struct TN_ExchLinkQueue *exch_link_queue = + _tn_get_exch_link_queue_by_exch_link(exch_link); + + void *p_msg = NULL; + + rc = tn_is_task_context() + ? tn_fmem_get(exch_link_queue->fmem, &p_msg, TN_WAIT_INFINITE) + : tn_fmem_iget_polling(exch_link_queue->fmem, &p_msg); + + if (rc != TN_RC_OK){ + //-- there was some error: just return rc as it is + } else { + //-- memory was received from fixed-memory pool, copy data there + _tn_memcpy_uword( + p_msg, + exch_link->exch->data, + _TN_SIZE_BYTES_TO_UWORDS(exch_link->exch->size) + ); + + //-- put it to the queue + rc = tn_is_task_context() + ? tn_queue_send(exch_link_queue->queue, p_msg, TN_WAIT_INFINITE) + : tn_queue_isend_polling(exch_link_queue->queue, p_msg); + if (rc != TN_RC_OK){ + //-- there was some error while sending the message, + // so before we return, we should free buffer that we've allocated + rc = tn_is_task_context() + ? tn_fmem_release(exch_link_queue->fmem, p_msg) + : tn_fmem_irelease(exch_link_queue->fmem, p_msg); + } else { + //-- everything is fine, so, leave rc = TN_RC_OK + } + + } + + return rc; +} + +static enum TN_RCode _dtor(struct TN_ExchLink *exch_link) +{ + //-- just call desctructor of superclass + return _tn_exch_link_vtable()->dtor(exch_link); +} + + + + + + + +/******************************************************************************* + * PUBLIC FUNCTIONS + ******************************************************************************/ + +enum TN_RCode tn_exch_link_queue_create( + struct TN_ExchLinkQueue *exch_link_queue, + struct TN_DQueue *queue, + struct TN_FMem *fmem + ) +{ + enum TN_RCode rc = _check_param_create(exch_link_queue, queue, fmem); + + if (rc == TN_RC_OK){ + //-- call constructor of superclass + rc = _tn_exch_link_create(&exch_link_queue->super); + } + + if (rc != TN_RC_OK){ + //-- just return rc as it is + } else { + //-- set the virtual functions table of this particular subclass + exch_link_queue->super.vtable = &_vtable; + + exch_link_queue->queue = queue; + exch_link_queue->fmem = fmem; + } + + return rc; +} + +enum TN_RCode tn_exch_link_queue_delete( + struct TN_ExchLinkQueue *exch_link_queue + ) +{ + return _tn_exch_link_delete(&exch_link_queue->super); +} + + + diff --git a/src/core/tn_exch_link_queue.h b/src/core/tn_exch_link_queue.h new file mode 100644 index 0000000..c22352b --- /dev/null +++ b/src/core/tn_exch_link_queue.h @@ -0,0 +1,132 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * \file + * + * Exchange link: queue (in terms of OOP, it's an "class, inherited from + * `#TN_ExchLink`"). + * + * For internal kernel usage only. + * + */ + + +#ifndef _TN_EXCH_LINK_QUEUE_H +#define _TN_EXCH_LINK_QUEUE_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "tn_exch_link.h" + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +struct TN_ExchLinkQueue; + + +/** + * Base structure for \ref tn_exch.h "exchange" link. + * + * For internal kernel usage only. + */ +struct TN_ExchLinkQueue { + /// + /// Exchange link: in terms of OOP, it's a superclass (or base class) + struct TN_ExchLink super; + /// + /// A pointer to queue to send messages to. + struct TN_DQueue *queue; + /// + /// A pointer to fixed-memory pool to get memory from. + /// Note: if data size is <= `sizeof(#TN_UWord)`, `fmem` might be `NULL`. + struct TN_FMem *fmem; +}; + + + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +/******************************************************************************* + * PUBLIC FUNCTION PROTOTYPES + ******************************************************************************/ + +enum TN_RCode tn_exch_link_queue_create( + struct TN_ExchLinkQueue *exch_link_queue, + struct TN_DQueue *queue, + struct TN_FMem *fmem + ); + +enum TN_RCode tn_exch_link_queue_delete( + struct TN_ExchLinkQueue *exch_link_queue + ); + +static inline struct TN_ExchLink *tn_exch_link_queue_base_get( + struct TN_ExchLinkQueue *exch_link_queue + ) +{ + return &exch_link_queue->super; +} + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // _TN_EXCH_LINK_QUEUE_H + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/tn_fmem.c b/src/core/tn_fmem.c index 189f432..9f9d4ee 100644 --- a/src/core/tn_fmem.c +++ b/src/core/tn_fmem.c @@ -49,6 +49,7 @@ //-- header of current module #include "tn_fmem.h" +#include "_tn_fmem.h" //-- header of other needed modules #include "tn_tasks.h" @@ -74,7 +75,7 @@ static inline enum TN_RCode _check_param_fmem_create(struct TN_FMem *fmem) if (fmem == NULL){ rc = TN_RC_WPARAM; - } else if (fmem->id_fmp == TN_ID_FSMEMORYPOOL){ + } else if (_tn_fmem_is_valid(fmem)){ rc = TN_RC_WPARAM; } @@ -87,7 +88,7 @@ static inline enum TN_RCode _check_param_fmem_delete(struct TN_FMem *fmem) if (fmem == NULL){ rc = TN_RC_WPARAM; - } else if (fmem->id_fmp != TN_ID_FSMEMORYPOOL){ + } else if (!_tn_fmem_is_valid(fmem)){ rc = TN_RC_INVALID_OBJ; } @@ -103,7 +104,7 @@ static inline enum TN_RCode _check_param_job_perform( if (fmem == NULL || p_data == NULL){ rc = TN_RC_WPARAM; - } else if (fmem->id_fmp != TN_ID_FSMEMORYPOOL){ + } else if (!_tn_fmem_is_valid(fmem)){ rc = TN_RC_INVALID_OBJ; } diff --git a/src/core/tn_sys.c b/src/core/tn_sys.c index dcf4fa2..660d522 100644 --- a/src/core/tn_sys.c +++ b/src/core/tn_sys.c @@ -489,3 +489,17 @@ void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task) } #endif +/** + * @param size_uwords size in uwords + */ +void _tn_memcpy_uword( + TN_UWord *tgt, const TN_UWord *src, unsigned int size_uwords + ) +{ + int i; + for (i = 0; i < size_uwords; i++){ + *tgt++ = *src++; + } +} + + diff --git a/stuff/vimwiki/index.wiki b/stuff/vimwiki/index.wiki index a0163c7..2862eaf 100644 --- a/stuff/vimwiki/index.wiki +++ b/stuff/vimwiki/index.wiki @@ -8,14 +8,28 @@ == Routine == + * [ ] Exchange object + * [ ] probably move _tn_memcpy_uword() to something like `tn_util.c` + + +=== exchange methods === + + * tn_exch_create + * tn_exch_delete + * tn_exch_link_add + * tn_exch_link_remove + * + * tn_read + * tn_write + * tn_iwrite + * + * tn_lock + * tn_unlock + * tn_unlock_and_notify + * tn_iunlock_and_notify == Plans == - * [.] Event group connection (at least, it would be useful to connect event group to queue) - * [X] implement functionality - * [ ] implement tests - * [ ] implement example - * [ ] add the link to example from `tn_eventgrp.h` * [ ] Exchange object: see AVIX User Guide & Reference Guide, 6.6.8 * [ ] Event group: probably, add mask of flags that should be cleared automatically when any task `wait`s for it * [ ] Add a destroy callback for each task, this callback (if not NULL) should be called whenever task is terminated with `tn_task_exit()` or `tn_task_terminate()`. From 745178dcf72377650a83966674d4e89fd8989167 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Wed, 22 Oct 2014 18:20:12 +0400 Subject: [PATCH 09/96] for each kernel object, added protected function _tn__is_valid() --- src/core/internal/_tn_dqueue.h | 2 - src/core/internal/_tn_eventgrp.h | 12 ++++ src/core/internal/_tn_exch.h | 13 ++++ src/core/internal/_tn_exch_link.h | 13 ++++ src/core/internal/_tn_fmem.h | 2 - src/core/internal/_tn_mutex.h | 13 ++++ src/core/internal/_tn_sem.h | 100 ++++++++++++++++++++++++++++++ src/core/internal/_tn_tasks.h | 13 ++++ src/core/internal/_tn_timer.h | 12 ++++ src/core/tn_eventgrp.c | 4 +- src/core/tn_exch.c | 4 +- src/core/tn_exch_link.c | 4 +- src/core/tn_mutex.c | 4 +- src/core/tn_sem.c | 6 +- src/core/tn_tasks.c | 6 +- src/core/tn_timer.c | 4 +- 16 files changed, 192 insertions(+), 20 deletions(-) create mode 100644 src/core/internal/_tn_sem.h diff --git a/src/core/internal/_tn_dqueue.h b/src/core/internal/_tn_dqueue.h index f5fdfee..aa87b8b 100644 --- a/src/core/internal/_tn_dqueue.h +++ b/src/core/internal/_tn_dqueue.h @@ -55,8 +55,6 @@ extern "C" { /*}*/ * EXTERNAL TYPES ******************************************************************************/ -struct TN_Exch; - /******************************************************************************* diff --git a/src/core/internal/_tn_eventgrp.h b/src/core/internal/_tn_eventgrp.h index de038c6..e8c4411 100644 --- a/src/core/internal/_tn_eventgrp.h +++ b/src/core/internal/_tn_eventgrp.h @@ -92,6 +92,18 @@ enum TN_RCode _tn_eventgrp_link_manage( +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_eventgrp_is_valid( + struct TN_EventGrp *eventgrp + ) +{ + return (eventgrp->id_event == TN_ID_EVENTGRP); +} + + #ifdef __cplusplus diff --git a/src/core/internal/_tn_exch.h b/src/core/internal/_tn_exch.h index c779ef0..23b360a 100644 --- a/src/core/internal/_tn_exch.h +++ b/src/core/internal/_tn_exch.h @@ -42,6 +42,7 @@ ******************************************************************************/ #include "_tn_sys.h" +#include "tn_exch.h" @@ -88,6 +89,18 @@ enum TN_RCode _tn_exch_read( +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_exch_is_valid( + struct TN_Exch *exch + ) +{ + return (exch->id_exch == TN_ID_EXCHANGE); +} + + #ifdef __cplusplus diff --git a/src/core/internal/_tn_exch_link.h b/src/core/internal/_tn_exch_link.h index 6d62727..c06b5b2 100644 --- a/src/core/internal/_tn_exch_link.h +++ b/src/core/internal/_tn_exch_link.h @@ -42,6 +42,7 @@ ******************************************************************************/ #include "_tn_sys.h" +#include "tn_exch_link.h" @@ -93,6 +94,18 @@ enum TN_RCode _tn_exch_link_delete( +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_exch_link_is_valid( + struct TN_ExchLink *exch_link + ) +{ + return (exch_link->id_exch_link == TN_ID_EXCHANGE_LINK); +} + + #ifdef __cplusplus } /* extern "C" */ diff --git a/src/core/internal/_tn_fmem.h b/src/core/internal/_tn_fmem.h index 0a09dd2..35b689e 100644 --- a/src/core/internal/_tn_fmem.h +++ b/src/core/internal/_tn_fmem.h @@ -55,8 +55,6 @@ extern "C" { /*}*/ * EXTERNAL TYPES ******************************************************************************/ -struct TN_Exch; - /******************************************************************************* diff --git a/src/core/internal/_tn_mutex.h b/src/core/internal/_tn_mutex.h index 0f7ae12..28c3003 100644 --- a/src/core/internal/_tn_mutex.h +++ b/src/core/internal/_tn_mutex.h @@ -42,6 +42,7 @@ ******************************************************************************/ #include "_tn_sys.h" +#include "tn_mutex.h" @@ -95,6 +96,18 @@ static inline void _tn_mutex_on_task_wait_complete(struct TN_Task *task) {} +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_mutex_is_valid( + struct TN_Mutex *mutex + ) +{ + return (mutex->id_mutex == TN_ID_MUTEX); +} + + diff --git a/src/core/internal/_tn_sem.h b/src/core/internal/_tn_sem.h new file mode 100644 index 0000000..2af2fb3 --- /dev/null +++ b/src/core/internal/_tn_sem.h @@ -0,0 +1,100 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __TN_SEM_H +#define __TN_SEM_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "_tn_sys.h" +#include "tn_sem.h" + + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * EXTERNAL TYPES + ******************************************************************************/ + + + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_sem_is_valid( + struct TN_Sem *sem + ) +{ + return (sem->id_sem == TN_ID_SEMAPHORE); +} + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_SEM_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + + diff --git a/src/core/internal/_tn_tasks.h b/src/core/internal/_tn_tasks.h index c0b20ad..7442239 100644 --- a/src/core/internal/_tn_tasks.h +++ b/src/core/internal/_tn_tasks.h @@ -42,6 +42,7 @@ ******************************************************************************/ #include "_tn_sys.h" +#include "tn_tasks.h" @@ -260,6 +261,18 @@ BOOL _tn_task_first_wait_complete( +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_task_is_valid( + struct TN_Task *task + ) +{ + return (task->id_task == TN_ID_TASK); +} + + #ifdef __cplusplus } /* extern "C" */ diff --git a/src/core/internal/_tn_timer.h b/src/core/internal/_tn_timer.h index c2780e7..2471f86 100644 --- a/src/core/internal/_tn_timer.h +++ b/src/core/internal/_tn_timer.h @@ -138,6 +138,18 @@ TN_Timeout _tn_timer_time_left(struct TN_Timer *timer); +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +static inline BOOL _tn_timer_is_valid( + struct TN_Timer *timer + ) +{ + return (timer->id_timer == TN_ID_TIMER); +} + + #ifdef __cplusplus } /* extern "C" */ diff --git a/src/core/tn_eventgrp.c b/src/core/tn_eventgrp.c index d210324..6615494 100644 --- a/src/core/tn_eventgrp.c +++ b/src/core/tn_eventgrp.c @@ -72,7 +72,7 @@ static inline enum TN_RCode _check_param_generic( if (eventgrp == NULL){ rc = TN_RC_WPARAM; - } else if (eventgrp->id_event != TN_ID_EVENTGRP){ + } else if (!_tn_eventgrp_is_valid(eventgrp)){ rc = TN_RC_INVALID_OBJ; } @@ -99,7 +99,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (eventgrp == NULL || eventgrp->id_event == TN_ID_EVENTGRP){ + if (eventgrp == NULL || _tn_eventgrp_is_valid(eventgrp)){ rc = TN_RC_WPARAM; } diff --git a/src/core/tn_exch.c b/src/core/tn_exch.c index a718cd3..7201c2c 100644 --- a/src/core/tn_exch.c +++ b/src/core/tn_exch.c @@ -85,7 +85,7 @@ static inline enum TN_RCode _check_param_generic( if (exch == NULL){ rc = TN_RC_WPARAM; - } else if (exch->id_exch != TN_ID_EXCHANGE){ + } else if (!_tn_exch_is_valid(exch)){ rc = TN_RC_INVALID_OBJ; } @@ -100,7 +100,7 @@ static inline enum TN_RCode _check_param_create( if (exch == NULL){ rc = TN_RC_WPARAM; - } else if (exch->id_exch == TN_ID_EXCHANGE){ + } else if (_tn_exch_is_valid(exch)){ rc = TN_RC_WPARAM; } diff --git a/src/core/tn_exch_link.c b/src/core/tn_exch_link.c index 3c09c9e..1ecb116 100644 --- a/src/core/tn_exch_link.c +++ b/src/core/tn_exch_link.c @@ -103,7 +103,7 @@ static inline enum TN_RCode _check_param_generic( if (exch_link == NULL){ rc = TN_RC_WPARAM; - } else if (exch_link->id_exch_link != TN_ID_EXCHANGE_LINK){ + } else if (!_tn_exch_link_is_valid(exch_link)){ rc = TN_RC_INVALID_OBJ; } @@ -118,7 +118,7 @@ static inline enum TN_RCode _check_param_create( if (exch_link == NULL){ rc = TN_RC_WPARAM; - } else if (exch_link->id_exch_link == TN_ID_EXCHANGE_LINK){ + } else if (_tn_exch_link_is_valid(exch_link)){ rc = TN_RC_WPARAM; } diff --git a/src/core/tn_mutex.c b/src/core/tn_mutex.c index 80b60b5..b36d29c 100644 --- a/src/core/tn_mutex.c +++ b/src/core/tn_mutex.c @@ -97,7 +97,7 @@ static inline enum TN_RCode _check_param_generic( if (mutex == NULL){ rc = TN_RC_WPARAM; - } else if (mutex->id_mutex != TN_ID_MUTEX){ + } else if (!_tn_mutex_is_valid(mutex)){ rc = TN_RC_INVALID_OBJ; } @@ -114,7 +114,7 @@ static inline enum TN_RCode _check_param_create( if (mutex == NULL){ rc = TN_RC_WPARAM; - } else if (mutex->id_mutex == TN_ID_MUTEX){ + } else if (_tn_mutex_is_valid(mutex)){ rc = TN_RC_WPARAM; } else if ( protocol != TN_MUTEX_PROT_CEILING && protocol != TN_MUTEX_PROT_INHERIT) diff --git a/src/core/tn_sem.c b/src/core/tn_sem.c index 6ab68ec..98ec93b 100644 --- a/src/core/tn_sem.c +++ b/src/core/tn_sem.c @@ -48,7 +48,7 @@ //-- header of current module -#include "tn_sem.h" +#include "_tn_sem.h" //-- header of other needed modules #include "tn_tasks.h" @@ -70,7 +70,7 @@ static inline enum TN_RCode _check_param_generic( if (sem == NULL){ rc = TN_RC_WPARAM; - } else if (sem->id_sem != TN_ID_SEMAPHORE){ + } else if (!_tn_sem_is_valid(sem)){ rc = TN_RC_INVALID_OBJ; } @@ -91,7 +91,7 @@ static inline enum TN_RCode _check_param_create( if (sem == NULL){ rc = TN_RC_WPARAM; } else if (0 - || sem->id_sem == TN_ID_SEMAPHORE + || _tn_sem_is_valid(sem) || max_count <= 0 || start_count < 0 || start_count > max_count diff --git a/src/core/tn_tasks.c b/src/core/tn_tasks.c index 5584c6e..1bbbf10 100644 --- a/src/core/tn_tasks.c +++ b/src/core/tn_tasks.c @@ -49,7 +49,7 @@ //-- header of current module -#include "tn_tasks.h" +#include "_tn_tasks.h" //-- header of other needed modules #include "tn_mutex.h" @@ -76,7 +76,7 @@ static inline enum TN_RCode _check_param_generic( if (task == NULL){ rc = TN_RC_WPARAM; - } else if (task->id_task != TN_ID_TASK){ + } else if (!_tn_task_is_valid(task)){ rc = TN_RC_INVALID_OBJ; } @@ -392,7 +392,7 @@ enum TN_RCode tn_task_create( || task_func == NULL || task == NULL || task_stack_low_addr == NULL - || task->id_task == TN_ID_TASK + || _tn_task_is_valid(task) ) { return TN_RC_WPARAM; diff --git a/src/core/tn_timer.c b/src/core/tn_timer.c index 7693fac..dd11bcd 100644 --- a/src/core/tn_timer.c +++ b/src/core/tn_timer.c @@ -103,7 +103,7 @@ static inline enum TN_RCode _check_param_generic( if (timer == NULL){ rc = TN_RC_WPARAM; - } else if (timer->id_timer != TN_ID_TIMER){ + } else if (!_tn_timer_is_valid(timer)){ rc = TN_RC_INVALID_OBJ; } @@ -119,7 +119,7 @@ static inline enum TN_RCode _check_param_create( if (timer == NULL){ rc = TN_RC_WPARAM; - } else if (timer->id_timer == TN_ID_TIMER){ + } else if (_tn_timer_is_valid(timer)){ rc = TN_RC_WPARAM; } From 778f376fe4d1b7c440c602151045ee9e8e779fad Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Wed, 22 Oct 2014 19:25:47 +0400 Subject: [PATCH 10/96] internal kernel comments improved --- src/core/internal/_tn_dqueue.h | 4 + src/core/internal/_tn_eventgrp.h | 42 +++++- src/core/internal/_tn_exch.h | 4 + src/core/internal/_tn_exch_link.h | 4 + src/core/internal/_tn_fmem.h | 4 + src/core/internal/_tn_mutex.h | 10 ++ src/core/internal/_tn_sem.h | 4 + src/core/internal/_tn_sys.h | 59 ++++++++- src/core/internal/_tn_tasks.h | 209 +++++++++++++++++++++++------- src/core/internal/_tn_timer.h | 4 + src/core/tn_sys.c | 19 ++- src/core/tn_sys.h | 19 ++- src/core/tn_tasks.c | 9 +- 13 files changed, 313 insertions(+), 78 deletions(-) diff --git a/src/core/internal/_tn_dqueue.h b/src/core/internal/_tn_dqueue.h index aa87b8b..0017b10 100644 --- a/src/core/internal/_tn_dqueue.h +++ b/src/core/internal/_tn_dqueue.h @@ -75,6 +75,10 @@ extern "C" { /*}*/ * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given queue object is valid + * (actually, just checks against `id_dque` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_dqueue_is_valid( struct TN_DQueue *dqueue ) diff --git a/src/core/internal/_tn_eventgrp.h b/src/core/internal/_tn_eventgrp.h index e8c4411..b786af8 100644 --- a/src/core/internal/_tn_eventgrp.h +++ b/src/core/internal/_tn_eventgrp.h @@ -70,7 +70,21 @@ extern "C" { /*}*/ ******************************************************************************/ /** - * Establish link to the event group + * Establish link to the event group. + * + * \attention Caller must disable interrupts. + * + * @param eventgrp_link + * eventgrp_link object which should be modified. The structure + * `eventgrp_link` is typically contained in some other structure, + * for example, #TN_DQueue. + * + * @param eventgrp + * Event group object to connect + * + * @param pattern + * Flags pattern that should be maintained by object to which + * event group is being connected. Can't be 0. */ enum TN_RCode _tn_eventgrp_link_set( struct TN_EGrpLink *eventgrp_link, @@ -79,12 +93,32 @@ enum TN_RCode _tn_eventgrp_link_set( ); /** - * Reset link to the event group (no matter whether it is already established) + * Reset link to the event group, i.e. make it non connected to any event + * group. (no matter whether it is already established). */ enum TN_RCode _tn_eventgrp_link_reset( struct TN_EGrpLink *eventgrp_link ); +/** + * Set or clear flag(s) in the connected event group, if any. Flag(s) are + * specified by `pattern` argument given to `#_tn_eventgrp_link_set()`. + * + * If given `eventgrp_link` doesn't contain any connected event group, nothing + * is performed and no error returned. + * + * \attention Caller must disable interrupts. + * + * @param eventgrp_link + * eventgrp_link object which contains connected event group. + * `eventgrp_link` is typically contained in some other structure, + * for example, #TN_DQueue. + * + * @param set + * - if `TRUE`, flag(s) are being set; + * - if `FALSE`, flag(s) are being cleared. + * + */ enum TN_RCode _tn_eventgrp_link_manage( struct TN_EGrpLink *eventgrp_link, BOOL set @@ -96,6 +130,10 @@ enum TN_RCode _tn_eventgrp_link_manage( * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given event group object is valid + * (actually, just checks against `id_event` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_eventgrp_is_valid( struct TN_EventGrp *eventgrp ) diff --git a/src/core/internal/_tn_exch.h b/src/core/internal/_tn_exch.h index 23b360a..e63ffab 100644 --- a/src/core/internal/_tn_exch.h +++ b/src/core/internal/_tn_exch.h @@ -93,6 +93,10 @@ enum TN_RCode _tn_exch_read( * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given exchange object is valid + * (actually, just checks against `id_exch` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_exch_is_valid( struct TN_Exch *exch ) diff --git a/src/core/internal/_tn_exch_link.h b/src/core/internal/_tn_exch_link.h index c06b5b2..bb9451a 100644 --- a/src/core/internal/_tn_exch_link.h +++ b/src/core/internal/_tn_exch_link.h @@ -98,6 +98,10 @@ enum TN_RCode _tn_exch_link_delete( * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given exchange link object is valid + * (actually, just checks against `id_exch_link` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_exch_link_is_valid( struct TN_ExchLink *exch_link ) diff --git a/src/core/internal/_tn_fmem.h b/src/core/internal/_tn_fmem.h index 35b689e..97542e8 100644 --- a/src/core/internal/_tn_fmem.h +++ b/src/core/internal/_tn_fmem.h @@ -75,6 +75,10 @@ extern "C" { /*}*/ * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given fixed memory pool object is valid + * (actually, just checks against `id_fmp` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_fmem_is_valid( struct TN_FMem *fmem ) diff --git a/src/core/internal/_tn_mutex.h b/src/core/internal/_tn_mutex.h index 28c3003..f0a4e19 100644 --- a/src/core/internal/_tn_mutex.h +++ b/src/core/internal/_tn_mutex.h @@ -89,6 +89,12 @@ void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task); void _tn_mutex_on_task_wait_complete(struct TN_Task *task); #else + +/* + * Mutexes are excluded from project: define some stub functions that + * are just compiled out. + */ + static inline void _tn_mutex_unlock_all_by_task(struct TN_Task *task) {} static inline void _tn_mutex_i_on_task_wait_complete(struct TN_Task *task) {} static inline void _tn_mutex_on_task_wait_complete(struct TN_Task *task) {} @@ -100,6 +106,10 @@ static inline void _tn_mutex_on_task_wait_complete(struct TN_Task *task) {} * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given mutex object is valid + * (actually, just checks against `id_mutex` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_mutex_is_valid( struct TN_Mutex *mutex ) diff --git a/src/core/internal/_tn_sem.h b/src/core/internal/_tn_sem.h index 2af2fb3..244502a 100644 --- a/src/core/internal/_tn_sem.h +++ b/src/core/internal/_tn_sem.h @@ -75,6 +75,10 @@ extern "C" { /*}*/ * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given semaphore object is valid + * (actually, just checks against `id_sem` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_sem_is_valid( struct TN_Sem *sem ) diff --git a/src/core/internal/_tn_sys.h b/src/core/internal/_tn_sys.h index cb4041b..9c73757 100644 --- a/src/core/internal/_tn_sys.h +++ b/src/core/internal/_tn_sys.h @@ -147,7 +147,7 @@ void _tn_wait_queue_notify_deleted(struct TN_ListItem *wait_queue); /** - * Set flags by bitmask. + * Set system flags by bitmask. * Given flags value will be OR-ed with existing flags. * * @return previous tn_sys_state value. @@ -163,14 +163,67 @@ enum TN_StateFlag _tn_sys_state_flags_set(enum TN_StateFlag flags); enum TN_StateFlag _tn_sys_state_flags_clear(enum TN_StateFlag flags); #if TN_MUTEX_DEADLOCK_DETECT +/** + * This function is called when deadlock becomes active or inactive + * (this is detected by mutex subsystem). + * + * @param active + * Boolean value indicating whether deadlock becomes active or inactive. + * Note: deadlock might become inactive if, for example, one of tasks + * involved in deadlock exits from waiting by timeout. + * + * @param mutex + * mutex that is involved in deadlock. You may find out other mutexes + * involved by means of `mutex->deadlock_list`. + * + * @param task + * task that is involved in deadlock. You may find out other tasks involved + * by means of `task->deadlock_list`. + * + */ void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task); #endif +/** + * memcpy that operates with `#TN_UWord`s. Note: memory overlapping isn't + * handled: data is always copied from lower addresses to higher ones. + * + * @param tgt + * Target memory address + * + * @param src + * Source memory address + * + * @param size_uwords + * Number of words to copy + * + */ +void _tn_memcpy_uword( + TN_UWord *tgt, const TN_UWord *src, unsigned int size_uwords + ); + + + + +/******************************************************************************* + * PROTECTED INLINE FUNCTIONS + ******************************************************************************/ + +/** + * Checks whether context switch is needed (that is, if currently running task + * is not the highest-priority task in the $(TN_TASK_STATE_RUNNABLE) state) + * + * @return `#TRUE` if context switch is needed + */ static inline BOOL _tn_need_context_switch(void) { return (tn_curr_run_task != tn_next_task_to_run); } +/** + * If context switch is needed (see `#_tn_need_context_switch()`), + * context switch is pended (see `#_tn_arch_context_switch_pend()`) + */ static inline void _tn_context_switch_pend_if_needed(void) { if (_tn_need_context_switch()){ @@ -178,10 +231,6 @@ static inline void _tn_context_switch_pend_if_needed(void) } } -void _tn_memcpy_uword( - TN_UWord *tgt, const TN_UWord *src, unsigned int size_uwords - ); - #ifdef __cplusplus } /* extern "C" */ diff --git a/src/core/internal/_tn_tasks.h b/src/core/internal/_tn_tasks.h index 7442239..1b4a05d 100644 --- a/src/core/internal/_tn_tasks.h +++ b/src/core/internal/_tn_tasks.h @@ -67,6 +67,10 @@ extern "C" { /*}*/ * DEFINITIONS ******************************************************************************/ +/** + * Get pointer to `struct #TN_Task` by pointer to the `task_queue` member + * of the `struct #TN_Task`. + */ #define _tn_get_task_by_tsk_queue(que) \ (que ? container_of(que, struct TN_Task, task_queue) : 0) @@ -77,87 +81,189 @@ extern "C" { /*}*/ * PROTECTED FUNCTION PROTOTYPES ******************************************************************************/ +//-- functions for each task state: set, clear, check {{{ + +//-- runnable {{{ + /** - * Callback that is given to `_tn_task_first_wait_complete()`, may perform - * any needed actions before waking task up, e.g. set some data in the `struct - * TN_Task` that task is waiting for. + * Bring task to the $(TN_TASK_STATE_RUNNABLE) state. + * Should be called when task_state is NONE. * - * @param task - * Task that is going to be waken up - * @param user_data_1 - * Arbitrary user data given to `_tn_task_first_wait_complete()` - * @param user_data_2 - * Arbitrary user data given to `_tn_task_first_wait_complete()` + * Set RUNNABLE bit in task_state, + * put task on the 'ready queue' for its priority, + * + * if priority of given `task` is higher than priority of + * `tn_next_task_to_run`, then set `tn_next_task_to_run` to given `task`. */ -typedef void (_TN_CBBeforeTaskWaitComplete)( - struct TN_Task *task, - void *user_data_1, - void *user_data_2 - ); +void _tn_task_set_runnable(struct TN_Task *task); +/** + * Bring task out from the $(TN_TASK_STATE_RUNNABLE) state. + * Should be called when task_state has just single RUNNABLE bit set. + * + * Clear RUNNABLE bit, remove task from 'ready queue', determine and set + * new `#tn_next_task_to_run`. + */ +void _tn_task_clear_runnable(struct TN_Task *task); +/** + * Returns whether given task is in $(TN_TASK_STATE_RUNNABLE) state. + */ static inline BOOL _tn_task_is_runnable(struct TN_Task *task) { return !!(task->task_state & TN_TASK_STATE_RUNNABLE); } +//}}} + +//-- wait {{{ + +/** + * Bring task to the $(TN_TASK_STATE_WAIT) state. + * Should be called when task_state is either NONE or $(TN_TASK_STATE_SUSPEND). + * + * @param task + * Task to bring to the $(TN_TASK_STATE_WAIT) state + * + * @param wait_que + * Wait queue to put task in, may be `#NULL`. If not `#NULL`, task is + * included in that list by `task_queue` member of `struct #TN_Task`. + * + * @param wait_reason + * Reason of waiting, see `enum #TN_WaitReason`. + * + * @param timeout + * If neither `0` nor `#TN_WAIT_INFINITE`, task will be woken up by timer + * after specified number of system ticks. + */ +void _tn_task_set_waiting( + struct TN_Task *task, + struct TN_ListItem *wait_que, + enum TN_WaitReason wait_reason, + TN_Timeout timeout + ); + +/** + * Bring task out from the $(TN_TASK_STATE_WAIT) state. + * Task must be already in the $(TN_TASK_STATE_WAIT) state. It may additionally + * be in the $(TN_TASK_STATE_SUSPEND) state. + * + * @param task + * Task to bring out from the $(TN_TASK_STATE_WAIT) state + * + * @param wait_rc + * return code that will be returned to waiting task from waited function. + */ +void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc); + +/** + * Returns whether given task is in $(TN_TASK_STATE_WAIT) state. + * Note that this state could be combined with $(TN_TASK_STATE_SUSPEND) state. + */ static inline BOOL _tn_task_is_waiting(struct TN_Task *task) { return !!(task->task_state & TN_TASK_STATE_WAIT); } +//}}} + +//-- suspended {{{ + +/** + * Bring task to the $(TN_TASK_STATE_SUSPEND ) state. + * Should be called when `task_state` is either NONE or $(TN_TASK_STATE_WAIT). + * + * @param task + * Task to bring to the $(TN_TASK_STATE_SUSPEND) state + */ +void _tn_task_set_suspended(struct TN_Task *task); + +/** + * Bring task out from the $(TN_TASK_STATE_SUSPEND) state. + * Task must be already in the $(TN_TASK_STATE_SUSPEND) state. It may + * additionally be in the $(TN_TASK_STATE_WAIT) state. + * + * @param task + * Task to bring out from the $(TN_TASK_STATE_SUSPEND) state + */ +void _tn_task_clear_suspended(struct TN_Task *task); + +/** + * Returns whether given task is in $(TN_TASK_STATE_SUSPEND) state. + * Note that this state could be combined with $(TN_TASK_STATE_WAIT) state. + */ static inline BOOL _tn_task_is_suspended(struct TN_Task *task) { return !!(task->task_state & TN_TASK_STATE_SUSPEND); } -static inline BOOL _tn_task_is_dormant(struct TN_Task *task) -{ - return !!(task->task_state & TN_TASK_STATE_DORMANT); -} +//}}} + +//-- dormant {{{ /** + * Bring task to the $(TN_TASK_STATE_DORMANT) state. * Should be called when task_state is NONE. * - * Set RUNNABLE bit in task_state, - * put task on the 'ready queue' for its priority, - * - * if priority is higher than tn_next_task_to_run's priority, - * then set tn_next_task_to_run to this task and return TRUE, - * otherwise return FALSE. + * Set DORMANT bit in task_state, reset task's priority to base value, + * reset time slice count to 0. */ -void _tn_task_set_runnable(struct TN_Task *task); - +void _tn_task_set_dormant(struct TN_Task* task); /** - * Should be called when task_state has just single RUNNABLE bit set. + * Bring task out from the $(TN_TASK_STATE_DORMANT) state. + * Should be called when task_state has just single DORMANT bit set. * - * Clear RUNNABLE bit, remove task from 'ready queue', determine and set - * new tn_next_task_to_run. + * Note: task's stack will be initialized inside this function (that is, + * `#_tn_arch_stack_init()` will be called) */ -void _tn_task_clear_runnable(struct TN_Task *task); - -void _tn_task_set_waiting( - struct TN_Task *task, - struct TN_ListItem *wait_que, - enum TN_WaitReason wait_reason, - TN_Timeout timeout - ); +void _tn_task_clear_dormant(struct TN_Task *task); /** - * @param wait_rc return code that will be returned to waiting task + * Returns whether given task is in $(TN_TASK_STATE_DORMANT) state. */ -void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc); +static inline BOOL _tn_task_is_dormant(struct TN_Task *task) +{ + return !!(task->task_state & TN_TASK_STATE_DORMANT); +} -void _tn_task_set_suspended(struct TN_Task *task); -void _tn_task_clear_suspended(struct TN_Task *task); +//}}} -void _tn_task_set_dormant(struct TN_Task* task); +//}}} -void _tn_task_clear_dormant(struct TN_Task *task); + +/** + * Callback that is given to `_tn_task_first_wait_complete()`, may perform + * any needed actions before waking task up, e.g. set some data in the `struct + * #TN_Task` that task is waiting for. + * + * @param task + * Task that is going to be waken up + * + * @param user_data_1 + * Arbitrary user data given to `_tn_task_first_wait_complete()` + * + * @param user_data_2 + * Arbitrary user data given to `_tn_task_first_wait_complete()` + */ +typedef void (_TN_CBBeforeTaskWaitComplete)( + struct TN_Task *task, + void *user_data_1, + void *user_data_2 + ); + +/** + * See the comment for tn_task_activate, tn_task_iactivate in the tn_tasks.h. + * + * It merely brings task out from the $(TN_TASK_STATE_DORMANT) state and + * brings it to the $(TN_TASK_STATE_RUNNABLE) state. + * + * If task is not in the `DORMANT` state, `#TN_RC_WSTATE` is returned. + */ enum TN_RCode _tn_task_activate(struct TN_Task *task); + /** * Should be called when task finishes waiting for anything. * @@ -176,11 +282,10 @@ static inline void _tn_task_wait_complete(struct TN_Task *task, enum TN_RCode wa /** - * calls _tn_task_clear_runnable() for current task, i.e. tn_curr_run_task - * Set task state to TN_TASK_STATE_WAIT, set given wait_reason and timeout. + * Should be called when task starts waiting for anything. * - * If non-NULL wait_que is provided, then add task to it; otherwise reset task's task_queue. - * If timeout is not TN_WAIT_INFINITE, add task to tn_wait_timeout_list + * It merely calls `#_tn_task_clear_runnable()` and then + * `#_tn_task_set_waiting()` for current task (`#tn_curr_run_task`). */ static inline void _tn_task_curr_to_wait_action( struct TN_ListItem *wait_que, @@ -194,7 +299,7 @@ static inline void _tn_task_curr_to_wait_action( /** - * Change priority of any task (runnable or non-runnable) + * Change priority of any task (either runnable or non-runnable) */ void _tn_change_task_priority(struct TN_Task *task, int new_priority); @@ -234,14 +339,18 @@ BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex); * * @param wait_queue * Wait queue to get first task from + * * @param wait_rc * Code that will be returned to woken-up task as a result of waiting * (this code is just given to `_tn_task_wait_complete()` actually) + * * @param callback * Callback function to call before wake task up, see * `#_TN_CBBeforeTaskWaitComplete`. Can be `NULL`. + * * @param user_data_1 * Arbitrary data that is passed to the callback + * * @param user_data_2 * Arbitrary data that is passed to the callback * @@ -265,6 +374,10 @@ BOOL _tn_task_first_wait_complete( * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given task object is valid + * (actually, just checks against `id_task` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_task_is_valid( struct TN_Task *task ) diff --git a/src/core/internal/_tn_timer.h b/src/core/internal/_tn_timer.h index 2471f86..d2aee4b 100644 --- a/src/core/internal/_tn_timer.h +++ b/src/core/internal/_tn_timer.h @@ -142,6 +142,10 @@ TN_Timeout _tn_timer_time_left(struct TN_Timer *timer); * PROTECTED INLINE FUNCTIONS ******************************************************************************/ +/** + * Checks whether given timer object is valid + * (actually, just checks against `id_timer` field, see `enum #TN_ObjId`) + */ static inline BOOL _tn_timer_is_valid( struct TN_Timer *timer ) diff --git a/src/core/tn_sys.c b/src/core/tn_sys.c index 660d522..d846c7d 100644 --- a/src/core/tn_sys.c +++ b/src/core/tn_sys.c @@ -408,8 +408,10 @@ TN_TaskBody *tn_cur_task_body_get(void) } + + /******************************************************************************* - * INTERNAL TNKERNEL FUNCTIONS + * PROTECTED FUNCTIONS ******************************************************************************/ /** @@ -439,10 +441,7 @@ void _tn_wait_queue_notify_deleted(struct TN_ListItem *wait_queue) } /** - * Set flags by bitmask. - * Given flags value will be OR-ed with existing flags. - * - * @return previous tn_sys_state value. + * See comments in the file _tn_sys.h */ enum TN_StateFlag _tn_sys_state_flags_set(enum TN_StateFlag flags) { @@ -452,10 +451,7 @@ enum TN_StateFlag _tn_sys_state_flags_set(enum TN_StateFlag flags) } /** - * Clear flags by bitmask - * Given flags value will be inverted and AND-ed with existing flags. - * - * @return previous tn_sys_state value. + * See comments in the file _tn_sys.h */ enum TN_StateFlag _tn_sys_state_flags_clear(enum TN_StateFlag flags) { @@ -466,6 +462,9 @@ enum TN_StateFlag _tn_sys_state_flags_clear(enum TN_StateFlag flags) #if TN_MUTEX_DEADLOCK_DETECT +/** + * See comments in the file _tn_sys.h + */ void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task) { if (active){ @@ -490,7 +489,7 @@ void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task) #endif /** - * @param size_uwords size in uwords + * See comments in the file _tn_sys.h */ void _tn_memcpy_uword( TN_UWord *tgt, const TN_UWord *src, unsigned int size_uwords diff --git a/src/core/tn_sys.h b/src/core/tn_sys.h index a448802..098e89b 100644 --- a/src/core/tn_sys.h +++ b/src/core/tn_sys.h @@ -181,13 +181,18 @@ typedef void (TN_CBIdle)(void); * deadlock becomes active or inactive. * Note: this feature works if only `#TN_MUTEX_DEADLOCK_DETECT` is non-zero. * - * @param active if `TRUE`, deadlock becomes active, otherwise it becomes - * inactive (say, if task stopped waiting for mutex - * because of timeout) - * @param mutex mutex that is involved in deadlock. You may find out other - * mutexes involved by means of `mutex->deadlock_list`. - * @param task task that is involved in deadlock. You may find out other - * tasks involved by means of `task->deadlock_list`. + * @param active + * Boolean value indicating whether deadlock becomes active or inactive. + * Note: deadlock might become inactive if, for example, one of tasks + * involved in deadlock exits from waiting by timeout. + * + * @param mutex + * mutex that is involved in deadlock. You may find out other mutexes + * involved by means of `mutex->deadlock_list`. + * + * @param task + * task that is involved in deadlock. You may find out other tasks involved + * by means of `task->deadlock_list`. */ typedef void (TN_CBDeadlock)( BOOL active, diff --git a/src/core/tn_tasks.c b/src/core/tn_tasks.c index 1bbbf10..24492e1 100644 --- a/src/core/tn_tasks.c +++ b/src/core/tn_tasks.c @@ -908,11 +908,8 @@ void _tn_task_set_waiting( // it is already reset in _tn_task_clear_runnable(). } - //--- Add to the timers queue - - if (timeout != TN_WAIT_INFINITE){ - _tn_timer_start(&task->timer, timeout); - } + //-- Add to the timers queue, if timeout is neither 0 nor `TN_WAIT_INFINITE`. + _tn_timer_start(&task->timer, timeout); } /** @@ -1036,7 +1033,7 @@ void _tn_task_clear_dormant(struct TN_Task *task) } /** - * See the comment for tn_task_activate, tn_task_iactivate in the tn_tasks.h + * See comment in the _tn_tasks.h file */ enum TN_RCode _tn_task_activate(struct TN_Task *task) { From 188a7f36e7789d2475b981a18a5639e5a9acebe4 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Wed, 22 Oct 2014 20:35:19 +0400 Subject: [PATCH 11/96] a little more comments changed --- src/core/internal/_tn_sys.h | 4 ++-- src/core/tn_timer.c | 9 +++++++-- stuff/vimwiki/index.wiki | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/core/internal/_tn_sys.h b/src/core/internal/_tn_sys.h index 9c73757..6953a60 100644 --- a/src/core/internal/_tn_sys.h +++ b/src/core/internal/_tn_sys.h @@ -84,8 +84,8 @@ extern struct TN_Task *tn_next_task_to_run; /// since this priority is used by idle task and it is always runnable. extern volatile unsigned int tn_ready_to_run_bmp; -/// system time that is get/set by `tn_sys_time_get()`, -/// respectively. +/// system time that can be returned by `tn_sys_time_get()`; it is also used +/// by tn_timer.h subsystem. extern volatile unsigned int tn_sys_time_count; /// current interrupt nesting count. Used by macros diff --git a/src/core/tn_timer.c b/src/core/tn_timer.c index dd11bcd..14099e7 100644 --- a/src/core/tn_timer.c +++ b/src/core/tn_timer.c @@ -60,7 +60,10 @@ * PUBLIC DATA ******************************************************************************/ +//-- see comments in the file _tn_timer.h struct TN_ListItem tn_timer_list__gen; + +//-- see comments in the file _tn_timer.h struct TN_ListItem tn_timer_list__tick[ TN_TICK_LISTS_CNT ]; @@ -81,6 +84,8 @@ struct TN_ListItem tn_timer_list__tick[ TN_TICK_LISTS_CNT ]; #endif /** + * Return index in the array `#tn_timer_list__tick`, based on given timeout. + * * @param timeout should be < TN_TICK_LISTS_CNT */ #define _TICK_LIST_INDEX(timeout) \ @@ -382,10 +387,10 @@ void _tn_timers_tick_proceed(void) ); //-- first of all, cancel timer, so that - // function could start it again if it wants to. + // callback function could start it again if it wants to. _tn_timer_cancel(timer); - //-- call user function + //-- call user callback function timer->func(timer, timer->p_user_data); } diff --git a/stuff/vimwiki/index.wiki b/stuff/vimwiki/index.wiki index 2862eaf..cb3e3da 100644 --- a/stuff/vimwiki/index.wiki +++ b/stuff/vimwiki/index.wiki @@ -39,6 +39,7 @@ * [ ] Port to ARM * [ ] Probably port to PIC24/dsPIC * [ ] Test how much is it slower to use tn_arch_sr_save_int_dis()/tn_arch_sr_restore() instead of TN_INT_DIS_SAVE()/TN_INT_RESTORE() + * [ ] Optionally, check if stack pointer is overflowed on each context switch. From a4477e3ef254110d312c4d3a8a92269d4cc98885 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 24 Oct 2014 20:16:37 +0400 Subject: [PATCH 12/96] tn_list is now protected --- src/core/internal/_tn_list.h | 435 +++++++++++++++++++++++++++++++++++ src/core/tn_dqueue.c | 5 +- src/core/tn_eventgrp.c | 5 +- src/core/tn_exch.c | 5 +- src/core/tn_exch_link.c | 3 +- src/core/tn_exch_link.h | 1 + src/core/tn_fmem.c | 3 +- src/core/tn_list.c | 66 +++--- src/core/tn_list.h | 304 +----------------------- src/core/tn_mutex.c | 43 ++-- src/core/tn_sem.c | 3 +- src/core/tn_sys.c | 15 +- src/core/tn_tasks.c | 39 ++-- src/core/tn_timer.c | 31 +-- src/tn.h | 1 - stuff/doxygen/tn_doxyfile | 3 +- 16 files changed, 560 insertions(+), 402 deletions(-) create mode 100644 src/core/internal/_tn_list.h diff --git a/src/core/internal/_tn_list.h b/src/core/internal/_tn_list.h new file mode 100644 index 0000000..3122453 --- /dev/null +++ b/src/core/internal/_tn_list.h @@ -0,0 +1,435 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * \file + * Circular doubly linked list + */ + + + +#ifndef __TN_LIST_H +#define __TN_LIST_H + + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "tn_common.h" +#include "tn_list.h" + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +/******************************************************************************* + * PROTECTED DEFINITIONS + ******************************************************************************/ + +/* + * NOTE: a lot of helper macros below were taken from Linux kernel source, + * from the file include/linux/list.h + */ + + +/** + * _tn_list_entry - get the struct for this entry + * @ptr: the &struct TN_ListItem pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the TN_ListItem member within the struct. + */ +#define _tn_list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * _tn_list_for_each - iterate over a list + * @pos: the &struct TN_ListItem to use as a loop cursor. + * @head: the head for your list. + */ +#define _tn_list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +/** + * _tn_list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the TN_ListItem member within the struct. + * + * Note, that list is expected to be not empty. + */ +#define _tn_list_first_entry(ptr, type, member) \ + _tn_list_entry((ptr)->next, type, member) + +/** + * _tn_list_first_entry_remove - remove the first element from a list + * and return it + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the TN_ListItem member within the struct. + * + * Note, that list is expected to be not empty. + */ +#define _tn_list_first_entry_remove(ptr, type, member) \ + _tn_list_entry(_tn_list_remove_head(ptr), type, member) + +/** + * _tn_list_last_entry - get the last element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the TN_ListItem member within the struct. + * + * Note, that list is expected to be not empty. + */ +#define _tn_list_last_entry(ptr, type, member) \ + _tn_list_entry((ptr)->prev, type, member) + +/** + * _tn_list_first_entry_or_null - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the TN_ListItem member within the struct. + * + * Note that if the list is empty, it returns NULL. + */ +#define _tn_list_first_entry_or_null(ptr, type, member) \ + (!_tn_list_empty(ptr) ? _tn_list_first_entry(ptr, type, member) : NULL) + +/** + * _tn_list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the TN_ListItem member within the struct. + */ +#define _tn_list_next_entry(pos, member) \ + _tn_list_entry((pos)->member.next, typeof(*(pos)), member) + +/** + * _tn_list_prev_entry - get the prev element in list + * @pos: the type * to cursor + * @member: the name of the TN_ListItem member within the struct. + */ +#define _tn_list_prev_entry(pos, member) \ + _tn_list_entry((pos)->member.prev, typeof(*(pos)), member) + +/** + * _tn_list_for_each - iterate over a list + * @pos: the &struct TN_ListItem to use as a loop cursor. + * @head: the head for your list. + */ +#define _tn_list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * _tn_list_for_each_prev - iterate over a list backwards + * @pos: the &struct TN_ListItem to use as a loop cursor. + * @head: the head for your list. + */ +#define _tn_list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * _tn_list_for_each_safe - iterate over a list safe against removal of list + * entry + * @pos: the &struct TN_ListItem to use as a loop cursor. + * @n: another &struct TN_ListItem to use as temporary storage + * @head: the head for your list. + */ +#define _tn_list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * _tn_list_for_each_prev_safe - iterate over a list backwards safe against + * removal of list entry + * @pos: the &struct TN_ListItem to use as a loop cursor. + * @n: another &struct TN_ListItem to use as temporary storage + * @head: the head for your list. + */ +#define _tn_list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * _tn_list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + */ +#define _tn_list_for_each_entry(pos, head, member) \ + for (pos = _tn_list_first_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = _tn_list_next_entry(pos, member)) + +/** + * _tn_list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + */ +#define _tn_list_for_each_entry_reverse(pos, head, member) \ + for (pos = _tn_list_last_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = _tn_list_prev_entry(pos, member)) + +/** + * _tn_list_prepare_entry - prepare a pos entry for use in + * _tn_list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the TN_ListItem member within the struct. + * + * Prepares a pos entry for use as a start point in + * _tn_list_for_each_entry_continue(). + */ +#define _tn_list_prepare_entry(pos, head, member) \ + ((pos) ? : _tn_list_entry(head, typeof(*pos), member)) + +/** + * _tn_list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define _tn_list_for_each_entry_continue(pos, head, member) \ + for (pos = _tn_list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = _tn_list_next_entry(pos, member)) + +/** + * _tn_list_for_each_entry_continue_reverse - iterate backwards from the given + * point + * + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define _tn_list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = _tn_list_prev_entry(pos, member); \ + &pos->member != (head); \ + pos = _tn_list_prev_entry(pos, member)) + +/** + * _tn_list_for_each_entry_from - iterate over list of given type from the + * current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define _tn_list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = _tn_list_next_entry(pos, member)) + +/** + * _tn_list_for_each_entry_safe - iterate over list of given type safe against + * removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + */ +#define _tn_list_for_each_entry_safe(pos, n, head, member) \ + for (pos = _tn_list_first_entry(head, typeof(*pos), member), \ + n = _tn_list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = _tn_list_next_entry(n, member)) + +/** + * _tn_list_for_each_entry_safe_continue - continue list iteration safe against + * removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define _tn_list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = _tn_list_next_entry(pos, member), \ + n = _tn_list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = _tn_list_next_entry(n, member)) + +/** + * _tn_list_for_each_entry_safe_from - iterate over list from current point safe + * against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define _tn_list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = _tn_list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = _tn_list_next_entry(n, member)) + +/** + * _tn_list_for_each_entry_safe_reverse - iterate backwards over list safe + * against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the TN_ListItem member within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define _tn_list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = _tn_list_last_entry(head, typeof(*pos), member), \ + n = _tn_list_prev_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = _tn_list_prev_entry(n, member)) + +/** + * _tn_list_safe_reset_next - reset a stale _tn_list_for_each_entry_safe loop + * @pos: the loop cursor used in the _tn_list_for_each_entry_safe loop + * @n: temporary storage used in _tn_list_for_each_entry_safe + * @member: the name of the TN_ListItem member within the struct. + * + * _tn_list_safe_reset_next is not safe to use in general if the list may be + * modified concurrently (eg. the lock is dropped in the loop body). An + * exception to this is if the cursor element (pos) is pinned in the list, + * and _tn_list_safe_reset_next is called after re-taking the lock and before + * completing the current iteration of the loop body. + */ +#define _tn_list_safe_reset_next(pos, n, member) \ + n = _tn_list_next_entry(pos, member) + + + +/******************************************************************************* + * PROTECTED FUNCTION PROTOTYPES + ******************************************************************************/ + +/** + * Reset the list: make next and prev items to reference the list itself. + * As a result, we got empty list. + */ +void _tn_list_reset(struct TN_ListItem *list); + +/** + * Checks whether the list is empty. + */ +BOOL _tn_list_is_empty(struct TN_ListItem *list); + +/** + * Insert an entry at the beginning of the list. + * + * @param list + * List to which new item should be inserted + * + * @param entry + * New item to insert + */ +void _tn_list_add_head(struct TN_ListItem *list, struct TN_ListItem *entry); + +/** + * Insert an entry at the end of the list. + * + * @param list + * List to which new item should be inserted + * + * @param entry + * New item to insert + */ +void _tn_list_add_tail(struct TN_ListItem *list, struct TN_ListItem *entry); + +/** + * Remove first item from the list. + * + * @param list + * List from which first item should be removed. + */ +struct TN_ListItem *_tn_list_remove_head(struct TN_ListItem *list); + +/** + * Remove last item from the list. + * + * @param list + * List from which last item should be removed. + */ +struct TN_ListItem *_tn_list_remove_tail(struct TN_ListItem *list); + +/** + * Remove item from the list. Please note that the item itself is left + * untouched, only previous and next items are altered. If you need to + * additionally reset the item (making it an empty list), you should + * additionally call `_tn_list_reset()`. + * + * @param entry + * An entry to remove from the list (if any). + */ +void _tn_list_remove_entry(struct TN_ListItem *entry); + +/** + * Checks whether given item is contained in the list. Note that the list + * will be walked through from the beginning until the item is found, or + * until end of the list is reached, so on large lists it might take + * large time. + * + * @param list + * List which should be checked for the item + * + * @param entry + * Item to check. + */ +BOOL _tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // __TN_LIST_H + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/src/core/tn_dqueue.c b/src/core/tn_dqueue.c index d31c485..62607dd 100644 --- a/src/core/tn_dqueue.c +++ b/src/core/tn_dqueue.c @@ -45,6 +45,7 @@ //-- internal tnkernel headers #include "_tn_eventgrp.h" #include "_tn_tasks.h" +#include "_tn_list.h" #include "tn_dqueue.h" @@ -440,8 +441,8 @@ enum TN_RCode tn_queue_create( if (rc != TN_RC_OK){ //-- just return rc as it is } else { - tn_list_reset(&(dque->wait_send_list)); - tn_list_reset(&(dque->wait_receive_list)); + _tn_list_reset(&(dque->wait_send_list)); + _tn_list_reset(&(dque->wait_receive_list)); dque->data_fifo = data_fifo; dque->items_cnt = items_cnt; diff --git a/src/core/tn_eventgrp.c b/src/core/tn_eventgrp.c index 6615494..990b3e6 100644 --- a/src/core/tn_eventgrp.c +++ b/src/core/tn_eventgrp.c @@ -44,6 +44,7 @@ //-- internal tnkernel headers #include "_tn_eventgrp.h" #include "_tn_tasks.h" +#include "_tn_list.h" //-- header of current module @@ -164,7 +165,7 @@ static void _scan_event_waitqueue(struct TN_EventGrp *eventgrp) // checking ALL of the tasks waiting on the event. - tn_list_for_each_entry_safe( + _tn_list_for_each_entry_safe( task, tmp_task, &(eventgrp->wait_queue), task_queue ) { @@ -275,7 +276,7 @@ enum TN_RCode tn_eventgrp_create( //-- just return rc as it is } else { - tn_list_reset(&(eventgrp->wait_queue)); + _tn_list_reset(&(eventgrp->wait_queue)); eventgrp->pattern = initial_pattern; eventgrp->id_event = TN_ID_EVENTGRP; diff --git a/src/core/tn_exch.c b/src/core/tn_exch.c index 7201c2c..5e2baed 100644 --- a/src/core/tn_exch.c +++ b/src/core/tn_exch.c @@ -47,6 +47,7 @@ #include "_tn_sys.h" #include "_tn_exch.h" #include "_tn_exch_link.h" +#include "_tn_list.h" //-- header of current module @@ -120,7 +121,7 @@ static enum TN_RCode _notify_all( enum TN_RCode rc = TN_RC_OK; struct TN_ExchLink *exch_link; - tn_list_for_each_entry(exch_link, &(exch->links_list), links_list_item){ + _tn_list_for_each_entry(exch_link, &(exch->links_list), links_list_item){ rc = _tn_exch_link_notify(exch_link); if (rc != TN_RC_OK){ break; @@ -183,7 +184,7 @@ enum TN_RCode tn_exch_create( exch->size = size; //-- reset links_list - tn_list_reset(&(exch->links_list)); + _tn_list_reset(&(exch->links_list)); //-- set id exch->id_exch = TN_ID_EXCHANGE; diff --git a/src/core/tn_exch_link.c b/src/core/tn_exch_link.c index 1ecb116..27b696e 100644 --- a/src/core/tn_exch_link.c +++ b/src/core/tn_exch_link.c @@ -44,6 +44,7 @@ //-- internal tnkernel headers #include "_tn_exch_link.h" +#include "_tn_list.h" //-- header of current module @@ -191,7 +192,7 @@ enum TN_RCode _tn_exch_link_create( //_vtable_init(); exch_link->vtable = &_vtable; - tn_list_reset(&(exch_link->links_list_item)); + _tn_list_reset(&(exch_link->links_list_item)); exch_link->id_exch_link = TN_ID_EXCHANGE_LINK; } diff --git a/src/core/tn_exch_link.h b/src/core/tn_exch_link.h index 0264984..c97a71e 100644 --- a/src/core/tn_exch_link.h +++ b/src/core/tn_exch_link.h @@ -52,6 +52,7 @@ * INCLUDED FILES ******************************************************************************/ +#include "tn_common.h" #include "tn_list.h" diff --git a/src/core/tn_fmem.c b/src/core/tn_fmem.c index 9f9d4ee..29c5923 100644 --- a/src/core/tn_fmem.c +++ b/src/core/tn_fmem.c @@ -45,6 +45,7 @@ //-- internal tnkernel headers #include "_tn_tasks.h" +#include "_tn_list.h" //-- header of current module @@ -238,7 +239,7 @@ enum TN_RCode tn_fmem_create( fmem->blocks_cnt = blocks_cnt; //-- reset wait_queue - tn_list_reset(&(fmem->wait_queue)); + _tn_list_reset(&(fmem->wait_queue)); //-- init block pointers { diff --git a/src/core/tn_list.c b/src/core/tn_list.c index 423a803..ee3e181 100644 --- a/src/core/tn_list.c +++ b/src/core/tn_list.c @@ -35,28 +35,30 @@ ******************************************************************************/ #include "tn_common.h" -#include "tn_list.h" +#include "_tn_list.h" -//---------------------------------------------------------------------------- -// Circular double-linked list queue -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- -void tn_list_reset(struct TN_ListItem *list) +/* + * See comments in the header file tn_list.h + */ +void _tn_list_reset(struct TN_ListItem *list) { list->prev = list->next = list; } -//---------------------------------------------------------------------------- -BOOL tn_is_list_empty(struct TN_ListItem *list) +/* + * See comments in the header file tn_list.h + */ +BOOL _tn_list_is_empty(struct TN_ListItem *list) { return (list->next == list && list->prev == list); } -//---------------------------------------------------------------------------- -void tn_list_add_head(struct TN_ListItem *list, struct TN_ListItem *entry) +/* + * See comments in the header file tn_list.h + */ +void _tn_list_add_head(struct TN_ListItem *list, struct TN_ListItem *entry) { //-- Insert an entry at the head of the queue. @@ -66,8 +68,10 @@ void tn_list_add_head(struct TN_ListItem *list, struct TN_ListItem *entry) list->next = entry; } -//---------------------------------------------------------------------------- -void tn_list_add_tail(struct TN_ListItem *list, struct TN_ListItem *entry) +/* + * See comments in the header file tn_list.h + */ +void _tn_list_add_tail(struct TN_ListItem *list, struct TN_ListItem *entry) { //-- Insert an entry at the tail of the queue. @@ -77,8 +81,10 @@ void tn_list_add_tail(struct TN_ListItem *list, struct TN_ListItem *entry) list->prev = entry; } -//---------------------------------------------------------------------------- -struct TN_ListItem *tn_list_remove_head(struct TN_ListItem *list) +/* + * See comments in the header file tn_list.h + */ +struct TN_ListItem *_tn_list_remove_head(struct TN_ListItem *list) { //-- Remove and return an entry at the head of the queue. @@ -95,24 +101,30 @@ struct TN_ListItem *tn_list_remove_head(struct TN_ListItem *list) return entry; } -//---------------------------------------------------------------------------- -struct TN_ListItem *tn_list_remove_tail(struct TN_ListItem *list) +/* + * See comments in the header file tn_list.h + */ +struct TN_ListItem *_tn_list_remove_tail(struct TN_ListItem *list) { //-- Remove and return an entry at the tail of the queue. struct TN_ListItem *entry; - if(list->prev == list) + if (list->prev == list){ return (struct TN_ListItem *) 0; + } entry = list->prev; entry->prev->next = list; list->prev = entry->prev; + return entry; } -//---------------------------------------------------------------------------- -void tn_list_remove_entry(struct TN_ListItem *entry) +/* + * See comments in the header file tn_list.h + */ +void _tn_list_remove_entry(struct TN_ListItem *entry) { //-- Remove an entry from the queue. entry->prev->next = entry->next; @@ -127,13 +139,15 @@ void tn_list_remove_entry(struct TN_ListItem *entry) // to get the next item. } -//---------------------------------------------------------------------------- -BOOL tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry) +/* + * See comments in the header file tn_list.h + */ +BOOL _tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry) { BOOL ret = FALSE; struct TN_ListItem *item; - tn_list_for_each(item, list){ + _tn_list_for_each(item, list){ if (item == list){ ret = TRUE; break; @@ -143,10 +157,4 @@ BOOL tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry) return ret; } -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - diff --git a/src/core/tn_list.h b/src/core/tn_list.h index e61cd72..8f7023d 100644 --- a/src/core/tn_list.h +++ b/src/core/tn_list.h @@ -36,21 +36,19 @@ /** * \file - * Circular doubly linked list + * Circular doubly linked list, for internal kernel usage. */ -#ifndef _TN_UTILS_H -#define _TN_UTILS_H +#ifndef _TN_LIST_H +#define _TN_LIST_H /******************************************************************************* * INCLUDED FILES ******************************************************************************/ -#include "tn_common.h" - #ifdef __cplusplus extern "C" { /*}*/ #endif @@ -60,7 +58,7 @@ extern "C" { /*}*/ ******************************************************************************/ /** - * Circular doubly linked list + * Circular doubly linked list item, for internal kernel usage. */ struct TN_ListItem { /// @@ -79,308 +77,16 @@ struct TN_ListItem { * DEFINITIONS ******************************************************************************/ -/* - * NOTE: a lot of helper macros below were taken from Linux kernel source, - * from the file include/linux/list.h - */ - - -/** - * tn_list_entry - get the struct for this entry - * @ptr: the &struct TN_ListItem pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the TN_ListItem member within the struct. - */ -#define tn_list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * tn_list_for_each - iterate over a list - * @pos: the &struct TN_ListItem to use as a loop cursor. - * @head: the head for your list. - */ -#define tn_list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - - -/** - * tn_list_first_entry - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the TN_ListItem member within the struct. - * - * Note, that list is expected to be not empty. - */ -#define tn_list_first_entry(ptr, type, member) \ - tn_list_entry((ptr)->next, type, member) - -/** - * tn_list_first_entry_remove - remove the first element from a list - * and return it - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the TN_ListItem member within the struct. - * - * Note, that list is expected to be not empty. - */ -#define tn_list_first_entry_remove(ptr, type, member) \ - tn_list_entry(tn_list_remove_head(ptr), type, member) - -/** - * tn_list_last_entry - get the last element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the TN_ListItem member within the struct. - * - * Note, that list is expected to be not empty. - */ -#define tn_list_last_entry(ptr, type, member) \ - tn_list_entry((ptr)->prev, type, member) - -/** - * tn_list_first_entry_or_null - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the TN_ListItem member within the struct. - * - * Note that if the list is empty, it returns NULL. - */ -#define tn_list_first_entry_or_null(ptr, type, member) \ - (!tn_list_empty(ptr) ? tn_list_first_entry(ptr, type, member) : NULL) - -/** - * tn_list_next_entry - get the next element in list - * @pos: the type * to cursor - * @member: the name of the TN_ListItem member within the struct. - */ -#define tn_list_next_entry(pos, member) \ - tn_list_entry((pos)->member.next, typeof(*(pos)), member) - -/** - * tn_list_prev_entry - get the prev element in list - * @pos: the type * to cursor - * @member: the name of the TN_ListItem member within the struct. - */ -#define tn_list_prev_entry(pos, member) \ - tn_list_entry((pos)->member.prev, typeof(*(pos)), member) - -/** - * tn_list_for_each - iterate over a list - * @pos: the &struct TN_ListItem to use as a loop cursor. - * @head: the head for your list. - */ -#define tn_list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * tn_list_for_each_prev - iterate over a list backwards - * @pos: the &struct TN_ListItem to use as a loop cursor. - * @head: the head for your list. - */ -#define tn_list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); pos = pos->prev) - -/** - * tn_list_for_each_safe - iterate over a list safe against removal of list - * entry - * @pos: the &struct TN_ListItem to use as a loop cursor. - * @n: another &struct TN_ListItem to use as temporary storage - * @head: the head for your list. - */ -#define tn_list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * tn_list_for_each_prev_safe - iterate over a list backwards safe against - * removal of list entry - * @pos: the &struct TN_ListItem to use as a loop cursor. - * @n: another &struct TN_ListItem to use as temporary storage - * @head: the head for your list. - */ -#define tn_list_for_each_prev_safe(pos, n, head) \ - for (pos = (head)->prev, n = pos->prev; \ - pos != (head); \ - pos = n, n = pos->prev) - -/** - * tn_list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - */ -#define tn_list_for_each_entry(pos, head, member) \ - for (pos = tn_list_first_entry(head, typeof(*pos), member); \ - &pos->member != (head); \ - pos = tn_list_next_entry(pos, member)) - -/** - * tn_list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - */ -#define tn_list_for_each_entry_reverse(pos, head, member) \ - for (pos = tn_list_last_entry(head, typeof(*pos), member); \ - &pos->member != (head); \ - pos = tn_list_prev_entry(pos, member)) - -/** - * tn_list_prepare_entry - prepare a pos entry for use in - * tn_list_for_each_entry_continue() - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the TN_ListItem member within the struct. - * - * Prepares a pos entry for use as a start point in - * tn_list_for_each_entry_continue(). - */ -#define tn_list_prepare_entry(pos, head, member) \ - ((pos) ? : tn_list_entry(head, typeof(*pos), member)) - -/** - * tn_list_for_each_entry_continue - continue iteration over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define tn_list_for_each_entry_continue(pos, head, member) \ - for (pos = tn_list_next_entry(pos, member); \ - &pos->member != (head); \ - pos = tn_list_next_entry(pos, member)) - -/** - * tn_list_for_each_entry_continue_reverse - iterate backwards from the given - * point - * - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - * - * Start to iterate over list of given type backwards, continuing after - * the current position. - */ -#define tn_list_for_each_entry_continue_reverse(pos, head, member) \ - for (pos = tn_list_prev_entry(pos, member); \ - &pos->member != (head); \ - pos = tn_list_prev_entry(pos, member)) - -/** - * tn_list_for_each_entry_from - iterate over list of given type from the - * current point - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - * - * Iterate over list of given type, continuing from current position. - */ -#define tn_list_for_each_entry_from(pos, head, member) \ - for (; &pos->member != (head); \ - pos = tn_list_next_entry(pos, member)) - -/** - * tn_list_for_each_entry_safe - iterate over list of given type safe against - * removal of list entry - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - */ -#define tn_list_for_each_entry_safe(pos, n, head, member) \ - for (pos = tn_list_first_entry(head, typeof(*pos), member), \ - n = tn_list_next_entry(pos, member); \ - &pos->member != (head); \ - pos = n, n = tn_list_next_entry(n, member)) - -/** - * tn_list_for_each_entry_safe_continue - continue list iteration safe against - * removal - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - * - * Iterate over list of given type, continuing after current point, - * safe against removal of list entry. - */ -#define tn_list_for_each_entry_safe_continue(pos, n, head, member) \ - for (pos = tn_list_next_entry(pos, member), \ - n = tn_list_next_entry(pos, member); \ - &pos->member != (head); \ - pos = n, n = tn_list_next_entry(n, member)) - -/** - * tn_list_for_each_entry_safe_from - iterate over list from current point safe - * against removal - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - * - * Iterate over list of given type from current point, safe against - * removal of list entry. - */ -#define tn_list_for_each_entry_safe_from(pos, n, head, member) \ - for (n = tn_list_next_entry(pos, member); \ - &pos->member != (head); \ - pos = n, n = tn_list_next_entry(n, member)) - -/** - * tn_list_for_each_entry_safe_reverse - iterate backwards over list safe - * against removal - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the TN_ListItem member within the struct. - * - * Iterate backwards over list of given type, safe against removal - * of list entry. - */ -#define tn_list_for_each_entry_safe_reverse(pos, n, head, member) \ - for (pos = tn_list_last_entry(head, typeof(*pos), member), \ - n = tn_list_prev_entry(pos, member); \ - &pos->member != (head); \ - pos = n, n = tn_list_prev_entry(n, member)) - -/** - * tn_list_safe_reset_next - reset a stale tn_list_for_each_entry_safe loop - * @pos: the loop cursor used in the tn_list_for_each_entry_safe loop - * @n: temporary storage used in tn_list_for_each_entry_safe - * @member: the name of the TN_ListItem member within the struct. - * - * tn_list_safe_reset_next is not safe to use in general if the list may be - * modified concurrently (eg. the lock is dropped in the loop body). An - * exception to this is if the cursor element (pos) is pinned in the list, - * and tn_list_safe_reset_next is called after re-taking the lock and before - * completing the current iteration of the loop body. - */ -#define tn_list_safe_reset_next(pos, n, member) \ - n = tn_list_next_entry(pos, member) - - - /******************************************************************************* * PUBLIC FUNCTION PROTOTYPES ******************************************************************************/ -void tn_list_reset(struct TN_ListItem *list); -BOOL tn_is_list_empty(struct TN_ListItem *list); -void tn_list_add_head(struct TN_ListItem *list, struct TN_ListItem *entry); -void tn_list_add_tail(struct TN_ListItem *list, struct TN_ListItem *entry); -struct TN_ListItem *tn_list_remove_head(struct TN_ListItem *list); -struct TN_ListItem *tn_list_remove_tail(struct TN_ListItem *list); -void tn_list_remove_entry(struct TN_ListItem *entry); -BOOL tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry); - #ifdef __cplusplus } /* extern "C" */ #endif -#endif // _TN_UTILS_H +#endif // _TN_LIST_H /******************************************************************************* * end of file diff --git a/src/core/tn_mutex.c b/src/core/tn_mutex.c index b36d29c..88c5c96 100644 --- a/src/core/tn_mutex.c +++ b/src/core/tn_mutex.c @@ -45,6 +45,7 @@ //-- internal tnkernel headers #include "_tn_mutex.h" #include "_tn_tasks.h" +#include "_tn_list.h" //-- header of current module #include "tn_mutex.h" @@ -156,7 +157,7 @@ static inline int _find_max_blocked_priority(struct TN_Mutex *mutex, int ref_pri //-- Iterate through all the tasks that wait for lock mutex. // Highest priority (i.e. lowest number) will be returned eventually. - tn_list_for_each_entry(task, &(mutex->wait_queue), task_queue){ + _tn_list_for_each_entry(task, &(mutex->wait_queue), task_queue){ if(task->priority < priority){ //-- task priority is higher, remember it priority = task->priority; @@ -222,7 +223,7 @@ static void _update_task_priority(struct TN_Task *task) struct TN_Mutex *mutex; //-- Iterate through all the mutexes locked by given task - tn_list_for_each_entry(mutex, &(task->mutex_queue), mutex_queue){ + _tn_list_for_each_entry(mutex, &(task->mutex_queue), mutex_queue){ priority = _find_max_priority_by_mutex(mutex, priority); } } @@ -295,7 +296,7 @@ static inline void _mutex_do_lock(struct TN_Mutex *mutex, struct TN_Task *task) __mutex_lock_cnt_change(mutex, 1); //-- Add mutex to task's locked mutexes queue - tn_list_add_tail(&(task->mutex_queue), &(mutex->mutex_queue)); + _tn_list_add_tail(&(task->mutex_queue), &(mutex->mutex_queue)); //-- Determine new priority for the task { @@ -330,10 +331,10 @@ static void _link_deadlock_lists(struct TN_Mutex *mutex, struct TN_Task *task) struct TN_Mutex *mutex2 = _get_mutex_by_wait_queque(holder->pwait_queue); //-- link two tasks together - tn_list_add_tail(&task->deadlock_list, &holder->deadlock_list); + _tn_list_add_tail(&task->deadlock_list, &holder->deadlock_list); //-- link two mutexes together - tn_list_add_head(&mutex->deadlock_list, &mutex2->deadlock_list); + _tn_list_add_head(&mutex->deadlock_list, &mutex2->deadlock_list); if (_tn_is_mutex_locked_by_task(task, mutex2)){ //-- done; all mutexes and tasks involved in deadlock were linked together. @@ -360,14 +361,14 @@ static void _unlink_deadlock_lists(struct TN_Mutex *mutex, struct TN_Task *task) struct TN_ListItem *item; struct TN_ListItem *tmp_item; - tn_list_for_each_safe(item, tmp_item, &mutex->deadlock_list){ - tn_list_remove_entry(item); - tn_list_reset(item); + _tn_list_for_each_safe(item, tmp_item, &mutex->deadlock_list){ + _tn_list_remove_entry(item); + _tn_list_reset(item); } - tn_list_for_each_safe(item, tmp_item, &task->deadlock_list){ - tn_list_remove_entry(item); - tn_list_reset(item); + _tn_list_for_each_safe(item, tmp_item, &task->deadlock_list){ + _tn_list_remove_entry(item); + _tn_list_reset(item); } } @@ -437,9 +438,9 @@ static void _check_deadlock_active(struct TN_Mutex *mutex, struct TN_Task *task) */ static void _cry_deadlock_inactive(struct TN_Mutex *mutex, struct TN_Task *task) { - if (!tn_is_list_empty(&mutex->deadlock_list)){ + if (!_tn_list_is_empty(&mutex->deadlock_list)){ - if (tn_is_list_empty(&task->deadlock_list)){ + if (_tn_list_is_empty(&task->deadlock_list)){ //-- should never be here: deadlock lists for tasks and mutexes // should either be both non-empty or both empty _TN_FATAL_ERROR(); @@ -512,13 +513,13 @@ static void _mutex_do_unlock(struct TN_Mutex * mutex) mutex->cnt = 0; //-- Delete curr mutex from task's locked mutexes queue - tn_list_remove_entry(&(mutex->mutex_queue)); + _tn_list_remove_entry(&(mutex->mutex_queue)); //-- update priority for current holder _update_task_priority(mutex->holder); //-- Check for the task(s) that want to lock the mutex - if (tn_is_list_empty(&(mutex->wait_queue))){ + if (_tn_list_is_empty(&(mutex->wait_queue))){ //-- no more tasks want to lock the mutex, // so, set holder to NULL and return. mutex->holder = NULL; @@ -529,7 +530,7 @@ static void _mutex_do_unlock(struct TN_Mutex * mutex) struct TN_Task *task; //-- get first task from mutex's wait_queue - task = tn_list_first_entry( + task = _tn_list_first_entry( &(mutex->wait_queue), typeof(*task), task_queue ); @@ -577,10 +578,10 @@ enum TN_RCode tn_mutex_create( //-- just return rc as it is } else { - tn_list_reset(&(mutex->wait_queue)); - tn_list_reset(&(mutex->mutex_queue)); + _tn_list_reset(&(mutex->wait_queue)); + _tn_list_reset(&(mutex->mutex_queue)); #if TN_MUTEX_DEADLOCK_DETECT - tn_list_reset(&(mutex->deadlock_list)); + _tn_list_reset(&(mutex->deadlock_list)); #endif mutex->protocol = protocol; @@ -625,7 +626,7 @@ enum TN_RCode tn_mutex_delete(struct TN_Mutex *mutex) // be reset in tn_mutex_create() // // Probably we need to remove it. - tn_list_reset(&(mutex->mutex_queue)); + _tn_list_reset(&(mutex->mutex_queue)); } mutex->id_mutex = 0; //-- mutex does not exist now @@ -794,7 +795,7 @@ void _tn_mutex_unlock_all_by_task(struct TN_Task *task) // item is removed from the list // in _mutex_do_unlock(). - tn_list_for_each_entry_safe( + _tn_list_for_each_entry_safe( mutex, tmp_mutex, &(task->mutex_queue), mutex_queue ) { diff --git a/src/core/tn_sem.c b/src/core/tn_sem.c index 98ec93b..1f5338e 100644 --- a/src/core/tn_sem.c +++ b/src/core/tn_sem.c @@ -45,6 +45,7 @@ //-- internal tnkernel headers #include "_tn_tasks.h" +#include "_tn_list.h" //-- header of current module @@ -256,7 +257,7 @@ enum TN_RCode tn_sem_create( //-- just return rc as it is } else { - tn_list_reset(&(sem->wait_queue)); + _tn_list_reset(&(sem->wait_queue)); sem->count = start_count; sem->max_count = max_count; diff --git a/src/core/tn_sys.c b/src/core/tn_sys.c index d846c7d..3ca99f9 100644 --- a/src/core/tn_sys.c +++ b/src/core/tn_sys.c @@ -53,6 +53,7 @@ #include "_tn_sys.h" #include "_tn_timer.h" #include "_tn_tasks.h" +#include "_tn_list.h" #include "tn_tasks.h" @@ -148,15 +149,15 @@ static inline void _round_robin_manage(void) pri_queue = &(tn_ready_list[priority]); //-- If ready queue is not empty and there are more than 1 // task in the queue - if ( !(tn_is_list_empty((struct TN_ListItem *)pri_queue)) + if ( !(_tn_list_is_empty((struct TN_ListItem *)pri_queue)) && pri_queue->next->next != pri_queue ) { //-- Remove task from head and add it to the tail of //-- ready queue for current priority - curr_que = tn_list_remove_head(&(tn_ready_list[priority])); - tn_list_add_tail( + curr_que = _tn_list_remove_head(&(tn_ready_list[priority])); + _tn_list_add_tail( &(tn_ready_list[priority]), (struct TN_ListItem *)curr_que ); @@ -211,12 +212,12 @@ void tn_sys_start( // - reset list of runnable tasks with this priority // - reset time slice to `#TN_NO_TIME_SLICE` for (i = 0; i < TN_PRIORITIES_CNT; i++){ - tn_list_reset(&(tn_ready_list[i])); + _tn_list_reset(&(tn_ready_list[i])); tn_tslice_ticks[i] = TN_NO_TIME_SLICE; } //-- reset generic task queue and task count to 0 - tn_list_reset(&tn_create_queue); + _tn_list_reset(&tn_create_queue); tn_created_tasks_cnt = 0; //-- initial system flags: no flags set (see enum TN_StateFlag) @@ -428,13 +429,13 @@ void _tn_wait_queue_notify_deleted(struct TN_ListItem *wait_queue) //-- iterate through all tasks in the wait_queue, // calling _tn_task_wait_complete() for each task, // and setting TN_RC_DELETED as a wait return code. - tn_list_for_each_entry_safe(task, tmp_task, wait_queue, task_queue){ + _tn_list_for_each_entry_safe(task, tmp_task, wait_queue, task_queue){ //-- call _tn_task_wait_complete for every task _tn_task_wait_complete(task, TN_RC_DELETED); } #if TN_DEBUG - if (!tn_is_list_empty(wait_queue)){ + if (!_tn_list_is_empty(wait_queue)){ _TN_FATAL_ERROR(""); } #endif diff --git a/src/core/tn_tasks.c b/src/core/tn_tasks.c index 24492e1..19772f8 100644 --- a/src/core/tn_tasks.c +++ b/src/core/tn_tasks.c @@ -46,6 +46,7 @@ #include "_tn_tasks.h" #include "_tn_mutex.h" #include "_tn_timer.h" +#include "_tn_list.h" //-- header of current module @@ -94,13 +95,13 @@ static inline enum TN_RCode _check_param_generic( static inline void _init_mutex_queue(struct TN_Task *task) { - tn_list_reset(&(task->mutex_queue)); + _tn_list_reset(&(task->mutex_queue)); } #if TN_MUTEX_DEADLOCK_DETECT static inline void _init_deadlock_list(struct TN_Task *task) { - tn_list_reset(&(task->deadlock_list)); + _tn_list_reset(&(task->deadlock_list)); } #else # define _init_deadlock_list(task) @@ -196,7 +197,7 @@ static inline enum TN_RCode _task_delete(struct TN_Task *task) //-- Cannot delete not-terminated task rc = TN_RC_WSTATE; } else { - tn_list_remove_entry(&(task->create_queue)); + _tn_list_remove_entry(&(task->create_queue)); tn_created_tasks_cnt--; task->id_task = 0; } @@ -263,10 +264,10 @@ static inline BOOL _remove_entry_from_ready_queue(struct TN_ListItem *list_node, BOOL ret; //-- remove given list_node from the queue - tn_list_remove_entry(list_node); + _tn_list_remove_entry(list_node); //-- check if the queue for given priority is empty now - ret = tn_is_list_empty(&(tn_ready_list[priority])); + ret = _tn_list_is_empty(&(tn_ready_list[priority])); if (ret){ //-- list is empty, so, modify bitmask tn_ready_to_run_bmp @@ -278,7 +279,7 @@ static inline BOOL _remove_entry_from_ready_queue(struct TN_ListItem *list_node, static inline void _add_entry_to_ready_queue(struct TN_ListItem *list_node, int priority) { - tn_list_add_tail(&(tn_ready_list[priority]), list_node); + _tn_list_add_tail(&(tn_ready_list[priority]), list_node); tn_ready_to_run_bmp |= (1 << priority); } @@ -445,7 +446,7 @@ enum TN_RCode tn_task_create( //-- reset task_queue (the queue used to include task to runqueue or // waitqueue) - tn_list_reset(&(task->task_queue)); + _tn_list_reset(&(task->task_queue)); //-- init timer that is needed to implement task wait timeout _tn_timer_create(&task->timer, _task_wait_timeout, task); @@ -456,7 +457,7 @@ enum TN_RCode tn_task_create( _tn_task_set_dormant(task); //-- Add task to created task queue - tn_list_add_tail(&tn_create_queue, &(task->create_queue)); + _tn_list_add_tail(&tn_create_queue, &(task->create_queue)); tn_created_tasks_cnt++; if ((opts & TN_TASK_CREATE_OPT_START)){ @@ -869,7 +870,7 @@ void _tn_task_clear_runnable(struct TN_Task *task) } //-- and reset task's queue - tn_list_reset(&(task->task_queue)); + _tn_list_reset(&(task->task_queue)); } @@ -901,7 +902,7 @@ void _tn_task_set_waiting( //--- Add to the wait queue - FIFO if (wait_que != NULL){ - tn_list_add_tail(wait_que, &(task->task_queue)); + _tn_list_add_tail(wait_que, &(task->task_queue)); task->pwait_queue = wait_que; } else { //-- NOTE: we don't need to reset task_queue because @@ -928,7 +929,7 @@ void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc) _TN_FATAL_ERROR(""); } - if (tn_is_list_empty(&task->task_queue) != (task->pwait_queue == NULL)){ + if (_tn_list_is_empty(&task->task_queue) != (task->pwait_queue == NULL)){ _TN_FATAL_ERROR("task_queue and pwait_queue are out of sync"); } @@ -940,11 +941,11 @@ void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc) // get max blocked priority //-- NOTE: we don't care here whether task is contained in any wait_queue, - // because even if it isn't, tn_list_remove_entry() on empty list + // because even if it isn't, _tn_list_remove_entry() on empty list // does just nothing. - tn_list_remove_entry(&task->task_queue); + _tn_list_remove_entry(&task->task_queue); //-- and reset task's queue - tn_list_reset(&(task->task_queue)); + _tn_list_reset(&(task->task_queue)); //-- handle current wait_reason: say, for MUTEX_I, we should // handle priorities of other involved tasks. @@ -999,9 +1000,9 @@ void _tn_task_set_dormant(struct TN_Task* task) #if TN_DEBUG if (task->task_state != TN_TASK_STATE_NONE){ _TN_FATAL_ERROR(""); - } else if (!tn_is_list_empty(&task->mutex_queue)){ + } else if (!_tn_list_is_empty(&task->mutex_queue)){ _TN_FATAL_ERROR(""); - } else if (!tn_is_list_empty(&task->deadlock_list)){ + } else if (!_tn_list_is_empty(&task->deadlock_list)){ _TN_FATAL_ERROR(""); } #endif @@ -1062,12 +1063,12 @@ BOOL _tn_task_first_wait_complete( { BOOL ret = FALSE; - if (!(tn_is_list_empty(wait_queue))){ + if (!(_tn_list_is_empty(wait_queue))){ struct TN_Task *task; //-- there are tasks in the wait queue, so, wake up the first one //-- get first task from the wait_queue - task = tn_list_first_entry(wait_queue, typeof(*task), task_queue); + task = _tn_list_first_entry(wait_queue, typeof(*task), task_queue); //-- call provided callback (if any) if (callback != NULL){ @@ -1142,7 +1143,7 @@ BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex) BOOL ret = FALSE; struct TN_Mutex *tmp_mutex; - tn_list_for_each_entry(tmp_mutex, &(task->mutex_queue), mutex_queue){ + _tn_list_for_each_entry(tmp_mutex, &(task->mutex_queue), mutex_queue){ if (tmp_mutex == mutex){ ret = TRUE; break; diff --git a/src/core/tn_timer.c b/src/core/tn_timer.c index 14099e7..af86401 100644 --- a/src/core/tn_timer.c +++ b/src/core/tn_timer.c @@ -44,6 +44,7 @@ //-- internal tnkernel headers #include "_tn_timer.h" +#include "_tn_list.h" //-- header of current module @@ -292,11 +293,11 @@ void _tn_timers_init(void) int i; //-- reset "generic" timers list - tn_list_reset(&tn_timer_list__gen); + _tn_list_reset(&tn_timer_list__gen); //-- reset all "tick" timer lists for (i = 0; i < TN_TICK_LISTS_CNT; i++){ - tn_list_reset(&tn_timer_list__tick[i]); + _tn_list_reset(&tn_timer_list__tick[i]); } } @@ -326,7 +327,7 @@ void _tn_timers_tick_proceed(void) struct TN_Timer *timer; struct TN_Timer *tmp_timer; - tn_list_for_each_entry_safe( + _tn_list_for_each_entry_safe( timer, tmp_timer, &tn_timer_list__gen, timer_queue ) { @@ -345,8 +346,8 @@ void _tn_timers_tick_proceed(void) if (timer->timeout_cur < TN_TICK_LISTS_CNT){ //-- it's time to move this timer to the "tick" list - tn_list_remove_entry(&(timer->timer_queue)); - tn_list_add_tail( + _tn_list_remove_entry(&(timer->timer_queue)); + _tn_list_add_tail( &tn_timer_list__tick[_TICK_LIST_INDEX(timer->timeout_cur)], &(timer->timer_queue) ); @@ -371,7 +372,7 @@ void _tn_timers_tick_proceed(void) // fire NOW, unconditionally. //-- NOTE that we shouldn't use iterators like - // `tn_list_for_each_entry_safe()` here, because timers can be + // `_tn_list_for_each_entry_safe()` here, because timers can be // removed from the list while we are iterating through it: // this may happen if user-provided function cancels timer which // is in the same list. @@ -381,8 +382,8 @@ void _tn_timers_tick_proceed(void) // (because timeout 0 is disallowed, and timer with timeout // TN_TICK_LISTS_CNT is added to the "generic" list), // see implementation details in the tn_timer.h file - while (!tn_is_list_empty(p_cur_timer_list)){ - timer = tn_list_first_entry( + while (!_tn_list_is_empty(p_cur_timer_list)){ + timer = _tn_list_first_entry( p_cur_timer_list, typeof(*timer), timer_queue ); @@ -396,7 +397,7 @@ void _tn_timers_tick_proceed(void) #if TN_DEBUG //-- current "tick" list should be empty now - if (!tn_is_list_empty(p_cur_timer_list)){ + if (!_tn_list_is_empty(p_cur_timer_list)){ _TN_FATAL_ERROR(""); } #endif @@ -430,7 +431,7 @@ enum TN_RCode _tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout) int tick_list_index = _TICK_LIST_INDEX(timeout); timer->timeout_cur = tick_list_index; - tn_list_add_tail( + _tn_list_add_tail( &tn_timer_list__tick[ tick_list_index ], &(timer->timer_queue) ); @@ -439,7 +440,7 @@ enum TN_RCode _tn_timer_start(struct TN_Timer *timer, TN_Timeout timeout) // We should set timeout_cur adding current "tick" index to it. timer->timeout_cur = timeout + _TICK_LIST_INDEX(0); - tn_list_add_tail(&tn_timer_list__gen, &(timer->timer_queue)); + _tn_list_add_tail(&tn_timer_list__gen, &(timer->timer_queue)); } } @@ -465,10 +466,10 @@ enum TN_RCode _tn_timer_cancel(struct TN_Timer *timer) timer->timeout_cur = 0; //-- remove entry from timer queue - tn_list_remove_entry(&(timer->timer_queue)); + _tn_list_remove_entry(&(timer->timer_queue)); //-- reset the list - tn_list_reset(&(timer->timer_queue)); + _tn_list_reset(&(timer->timer_queue)); } return rc; @@ -489,7 +490,7 @@ enum TN_RCode _tn_timer_create( //-- just return rc as it is } else { - tn_list_reset(&(timer->timer_queue)); + _tn_list_reset(&(timer->timer_queue)); timer->timeout_cur = 0; timer->id_timer = TN_ID_TIMER; @@ -531,7 +532,7 @@ BOOL _tn_timer_is_active(struct TN_Timer *timer) } #endif - return (!tn_is_list_empty(&(timer->timer_queue))); + return (!_tn_list_is_empty(&(timer->timer_queue))); } /** diff --git a/src/tn.h b/src/tn.h index a2d3f50..0a0943d 100644 --- a/src/tn.h +++ b/src/tn.h @@ -56,7 +56,6 @@ #include "core/tn_mutex.h" #include "core/tn_sem.h" #include "core/tn_tasks.h" -#include "core/tn_list.h" #include "core/tn_exch.h" #include "core/tn_timer.h" diff --git a/stuff/doxygen/tn_doxyfile b/stuff/doxygen/tn_doxyfile index 21723da..78dcdd6 100644 --- a/stuff/doxygen/tn_doxyfile +++ b/stuff/doxygen/tn_doxyfile @@ -807,8 +807,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../../src/core/tn_list.h \ - ../../src/tn_cfg.h +EXCLUDE = ../../src/tn_cfg.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded From 9bf56274ea6c1e2f977b9ab5bcc08c64cdcf79a3 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sat, 25 Oct 2014 16:40:30 +0400 Subject: [PATCH 13/96] pic32 examples updated: added ability to use power-saving mode when idle task gets executed --- examples/common/arch/pic32/pic32_arch.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/examples/common/arch/pic32/pic32_arch.c b/examples/common/arch/pic32/pic32_arch.c index 318343d..ac4ed7c 100644 --- a/examples/common/arch/pic32/pic32_arch.c +++ b/examples/common/arch/pic32/pic32_arch.c @@ -122,13 +122,26 @@ void hw_init(void) { SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); - //turn off ADC function for all pins + //-- turn off ADC function for all pins AD1PCFG = 0xffffffff; - //-- enable timer5 interrupt + //-- Set power-saving mode to an idle mode + { + SYSKEY = 0x0; + SYSKEY = 0xAA996655; + SYSKEY = 0x556699AA; + + OSCCONCLR = 0x10; + + SYSKEY = 0x0; + } + + //-- enable timer5 interrupt. + // It is set to continue in the idle mode, so that system timer + // will wake system up each system tick. OpenTimer5((0 | T5_ON - | T5_IDLE_STOP + | T5_IDLE_CON | SYS_TMR_PRESCALER | T5_SOURCE_INT ), @@ -159,6 +172,10 @@ void hw_init(void) //-- idle callback that is called periodically from idle task void idle_task_callback (void) { + //TODO: uncomment if you want the idle task to use real power-saving mode. + // actual mode to use ("idle") is set up in the function hw_init(), + // here it is just activated. + //asm volatile ("wait"); } int32_t main(void) From 92450a80475aff4631a327902d1eba21bc1942a0 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 26 Oct 2014 15:44:11 +0300 Subject: [PATCH 14/96] MPLABX updated to 2.20, there are some changes in its project configurations.xml file --- src/arch/pic32/tneokernel.X/nbproject/configurations.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml index 9877bc2..64b858f 100644 --- a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml +++ b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml @@ -56,8 +56,17 @@ 2 + + + + + + false + false + + false From d67b134364fbf866aa7634b4f0e2bace60330d3d Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 04:52:06 +0400 Subject: [PATCH 15/96] added the very essentials of PIC24/dsPIC port --- .../basic/arch/pic24/.vimprj/.indexer_files | 6 + examples/basic/arch/pic24/.vimprj/my.vim | 68 + examples/basic/arch/pic24/tn_cfg_appl.h | 97 ++ .../pic24/tn_pic24_example_basic.X/Makefile | 113 ++ .../tn_pic24_example_basic.X.production.hex | 1093 +++++++++++++++++ .../nbproject/configurations.xml | 232 ++++ .../nbproject/project.properties | 0 .../nbproject/project.xml | 18 + .../basic/arch/pic24/tn_pic24_example_basic.c | 535 ++++++++ src/arch/pic24_dspic/tn_arch_pic24.S | 209 ++++ src/arch/pic24_dspic/tn_arch_pic24.h | 421 +++++++ src/arch/pic24_dspic/tn_arch_pic24_c.c | 99 ++ .../pic24_dspic/tneokernel_pic24.X/Makefile | 113 ++ .../nbproject/configurations.xml | 201 +++ .../nbproject/project.properties | 0 .../tneokernel_pic24.X/nbproject/project.xml | 16 + src/arch/tn_arch.h | 2 + stuff/vimwiki/index.wiki | 10 + 18 files changed, 3233 insertions(+) create mode 100644 examples/basic/arch/pic24/.vimprj/.indexer_files create mode 100644 examples/basic/arch/pic24/.vimprj/my.vim create mode 100644 examples/basic/arch/pic24/tn_cfg_appl.h create mode 100644 examples/basic/arch/pic24/tn_pic24_example_basic.X/Makefile create mode 100644 examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex create mode 100644 examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml create mode 100644 examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.properties create mode 100644 examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml create mode 100644 examples/basic/arch/pic24/tn_pic24_example_basic.c create mode 100644 src/arch/pic24_dspic/tn_arch_pic24.S create mode 100644 src/arch/pic24_dspic/tn_arch_pic24.h create mode 100644 src/arch/pic24_dspic/tn_arch_pic24_c.c create mode 100644 src/arch/pic24_dspic/tneokernel_pic24.X/Makefile create mode 100644 src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml create mode 100644 src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.properties create mode 100644 src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.xml diff --git a/examples/basic/arch/pic24/.vimprj/.indexer_files b/examples/basic/arch/pic24/.vimprj/.indexer_files new file mode 100644 index 0000000..3eb4912 --- /dev/null +++ b/examples/basic/arch/pic24/.vimprj/.indexer_files @@ -0,0 +1,6 @@ + +[tn_pic32_example_basic] +option:ctags_params = "--langmap=c:.c.h --languages=c" + +$INDEXER_PROJECT_ROOT + diff --git a/examples/basic/arch/pic24/.vimprj/my.vim b/examples/basic/arch/pic24/.vimprj/my.vim new file mode 100644 index 0000000..9411026 --- /dev/null +++ b/examples/basic/arch/pic24/.vimprj/my.vim @@ -0,0 +1,68 @@ +" config file for Vim's plugin "vimprj" + +" path to .vimprj folder +let s:sPath = expand(':p:h') + +" set .indexer_file to use +let g:indexer_indexerListFilename = s:sPath.'/.indexer_files' + +let g:indexer_getAllSubdirsFromIndexerListFile = 1 + +" project-specific format settings +let &tabstop = 3 +let &shiftwidth = 3 + +let s:o_dir = $INDEXER_PROJECT_ROOT.'/output/tmp/compiled_in_vim' + +if !isdirectory(s:o_dir) + call mkdir(s:o_dir, "p") +endif + +let g:indexer_handlePath = 0 + +call CheckNeededSymbols( + \ "The following items needs to be defined in your vimfiles/machine_local_conf/current/variables.vim file to make things work: ", + \ "", + \ [ + \ '$MACHINE_LOCAL_CONF__PATH__MICROCHIP_XC32', + \ ] + \ ) + +let s:sCompilerExecutable = '' +if has('win32') || has('win64') + let s:sCompilerExecutable = 'xc32-gcc.exe' +else + let s:sCompilerExecutable = 'xc32-gcc' +endif + +" Path to MPLAB .mcp project +let s:sProject = 'tn_pic32_example_basic.X' +call envcontrol#set_project_file($INDEXER_PROJECT_ROOT.'/'.s:sProject, 'MPLAB_X', { + \ 'parser_params': { + \ 'compiler_command_without_includes' : '' + \ .'"'.s:sCompilerExecutable.'" ' + \ .' -g -D__DEBUG -x c -c -mprocessor=32MX440F512H -Wall -mips16' + \ .' -Os -MMD -MF "'.s:o_dir.'/%:t:r.o.d" -o "'.s:o_dir.'/%:t:r.o"', + \ }, + \ 'handle_clang' : 1, + \ 'add_paths' : [ + \ $MACHINE_LOCAL_CONF__PATH__MICROCHIP_XC32.'/lib/gcc/pic32mx/4.5.2/include', + \ $MACHINE_LOCAL_CONF__PATH__MICROCHIP_XC32.'/pic32mx/include', + \ ], + \ 'clang_add_params' : '' + \ .' -D __C32__' + \ .' -D __C32_VERSION__=1210' + \ .' -D __CLANG_FOR_COMPLETION__' + \ .' -D __LANGUAGE_C__' + \ .' -D __PIC32MX__' + \ .' -D __32MX440F512H__' + \ .' -D __PIC32_FEATURE_SET__=440' + \ .' -D __DEBUG' + \ .' -Wno-builtin-requires-header' + \ .' -Wno-unused-value' + \ .' -Wno-implicit-function-declaration' + \ .' -Wno-attributes' + \ .' -Wno-invalid-source-encoding' + \ , + \ }) + diff --git a/examples/basic/arch/pic24/tn_cfg_appl.h b/examples/basic/arch/pic24/tn_cfg_appl.h new file mode 100644 index 0000000..ed35bfa --- /dev/null +++ b/examples/basic/arch/pic24/tn_cfg_appl.h @@ -0,0 +1,97 @@ + +/******************************************************************************* + * TNKernel configuration + * + ******************************************************************************/ + + +#ifndef _TN_CFG_H +#define _TN_CFG_H + + +/******************************************************************************* + * USER-DEFINED OPTIONS + ******************************************************************************/ + +/** + * Enables additional param checking for most of the system functions. + * It's surely useful for debug, but probably better to remove in release. + * If it is set, most of the system functions are able to return two additional + * codes: + * + * * `TN_RC_WPARAM` if wrong params were given; + * * `TN_RC_INVALID_OBJ` if given pointer doesn't point to a valid object. + * Object validity is checked by means of the special ID field of type + * `enum TN_ObjId`. + * + * @see `enum TN_ObjId` + */ +#define TN_CHECK_PARAM 1 + +/** + * Allows additional internal self-checking, useful to catch internal + * TNeoKernel bugs as well as illegal kernel usage (e.g. sleeping in the idle + * task callback). Produces a couple of extra instructions which usually just + * causes debugger to stop if something goes wrong. + */ +#define TN_DEBUG 1 + +/** + * Whether old TNKernel names (definitions, functions, etc) should be available. + * If you're porting your existing application written for TNKernel, + * it is definitely worth enabling. + * If you start new project with TNeoKernel, it's better to avoid old names. + */ +#define TN_OLD_TNKERNEL_NAMES 0 + +/* + * Whenter mutexes API should be available + */ +#define TN_USE_MUTEXES 1 + +/* + * Whether mutexes should allow recursive locking/unlocking + */ +#define TN_MUTEX_REC 1 + +/* + * Whether RTOS should detect deadlocks and notify user about them + * via callback (see tn_event_callback_set() function) + */ +#define TN_MUTEX_DEADLOCK_DETECT 1 + +/* + * API option for MAKE_ALIG() macro. + * + * There is a terrible mess with MAKE_ALIG() macro: TNKernel docs specify + * that the argument of it should be the size to align, but almost + * all ports, including "original" one, defined it so that it takes + * type, not size. + * + * But the port by AlexB implemented it differently + * (i.e. accordingly to the docs) + * + * When I was moving from the port by AlexB to another one, + * do you have any idea how much time it took me to figure out + * why do I have rare weird bug? :) + * + * So, available options: + * + * TN_API_MAKE_ALIG_ARG__TYPE: + * In this case, you should use macro like this: + * MAKE_ALIG(struct my_struct) + * This way is used in the majority of TNKernel ports. + * (actually, in all ports except the one by AlexB) + * + * TN_API_MAKE_ALIG_ARG__SIZE: + * In this case, you should use macro like this: + * MAKE_ALIG(sizeof(struct my_struct)) + * This way is stated in TNKernel docs + * and used in the port for dsPIC/PIC24/PIC32 by AlexB. + */ +#define TN_API_MAKE_ALIG_ARG TN_API_MAKE_ALIG_ARG__SIZE + + +#endif // _TN_CFG_H + + diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/Makefile b/examples/basic/arch/pic24/tn_pic24_example_basic.X/Makefile new file mode 100644 index 0000000..fca8e2c --- /dev/null +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/Makefile @@ -0,0 +1,113 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... +# WARNING: the IDE does not call this target since it takes a long time to +# simply run make. Instead, the IDE removes the configuration directories +# under build and dist directly without calling make. +# This target is left here so people can do a clean when running a clean +# outside the IDE. + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex b/examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex new file mode 100644 index 0000000..284f754 --- /dev/null +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex @@ -0,0 +1,1093 @@ +:020000040000fa +:080000000002040000000000f2 +:020000040000fa +:10040000cfdd20000e7f24000e01880000000000d8 +:100410000c000700a00422000100200011000700ca +:10042000000020000000e000020032000000020096 +:10043000000000004c1d0200000000000040da0037 +:100440000000fe004440a900000020000000e00081 +:100450000300320000002000a00188004440a800f2 +:100460000000060091018800800078000000eb0089 +:1004700015003700e280400032a0b4009101ba00bc +:10048000e280400032a0b4009102ba00e280400055 +:1004900032a0b4000002eb00472bde00f507b200eb +:1004a000602ce10004003a000059eb008301e900f0 +:1004b000fdff3e00040037006128e100010032002a +:1004c0000082eb00040007001101ba000200e00006 +:1004d000e8ff3a00000006003159ba008301e90044 +:1004e0000c0032002159ba008301e90008003200f3 +:1004f0000400e00003003a00e280400032a0b400b3 +:10050000f5ff370011d9ba008301e900faff3a007c +:100510008100e800e180400032a0b4000000060045 +:10052000b21c040000000000be1c0400000000001b +:10053000a41c040000000000301d040000000000a6 +:10054000361d0400000000005a03040000000000f3 +:100550005407040000000000e40c04000000000048 +:100560001008040000000000be1804000000000095 +:020000040000fa +:020000040005f5 +:0457f400003e000073 +:020000040000fa +:020000040005f5 +:0457f800ee3300008c +:020000040000fa +:020000040005f5 +:0457fc00609e0000ab +:020000040000fa +:10000800be1d0000a81d0000661d00007c1d00002c +:10001800921d0000be1d0000be1d0000be1d000098 +:10002800be1d0000be1d0000be1d0000761c0000a5 +:10003800be1d0000be1d0000be1d0000be1d00004c +:10004800be1d0000be1d0000be1d0000be1d00003c +:10005800be1d0000be1d0000be1d0000be1d00002c +:10006800be1d0000be1d0000be1d0000be1d00001c +:1000780010210000be1d0000be1d0000be1d0000b6 +:10008800be1d0000be1d0000be1d0000be1d0000fc +:10009800be1d0000be1d0000be1d0000be1d0000ec +:1000a800be1d0000be1d0000be1d0000be1d0000dc +:1000b800be1d0000be1d0000be1d0000be1d0000cc +:1000c800be1d0000be1d0000be1d0000be1d0000bc +:1000d800be1d0000be1d0000be1d0000be1d0000ac +:1000e800be1d0000be1d0000be1d0000be1d00009c +:1000f800be1d0000be1d0000be1d0000be1d00008c +:10010800be1d0000be1d0000be1d0000be1d00007b +:10011800be1d0000be1d0000be1d0000be1d00006b +:10012800be1d0000be1d0000be1d0000be1d00005b +:10013800be1d0000be1d0000be1d0000be1d00004b +:10014800be1d0000be1d0000be1d0000be1d00003b +:10015800be1d0000be1d0000be1d0000be1d00002b +:10016800be1d0000be1d0000be1d0000be1d00001b +:10017800be1d0000be1d0000be1d0000be1d00000b +:10018800be1d0000be1d0000be1d0000be1d0000fb +:10019800be1d0000be1d0000be1d0000be1d0000eb +:1001a800be1d0000be1d0000be1d0000be1d0000db +:1001b800be1d0000be1d0000be1d0000be1d0000cb +:1001c800be1d0000be1d0000be1d0000be1d0000bb +:1001d800be1d0000be1d0000be1d0000be1d0000ab +:1001e800be1d0000be1d0000be1d0000be1d00009b +:0801f800be1d0000be1d000049 +:020000040000fa +:10020800be1d0000a81d0000661d00007c1d00002a +:10021800921d0000be1d0000be1d0000be1d000096 +:10022800be1d0000be1d0000be1d0000761c0000a3 +:10023800be1d0000be1d0000be1d0000be1d00004a +:10024800be1d0000be1d0000be1d0000be1d00003a +:10025800be1d0000be1d0000be1d0000be1d00002a +:10026800be1d0000be1d0000be1d0000be1d00001a +:1002780010210000be1d0000be1d0000be1d0000b4 +:10028800be1d0000be1d0000be1d0000be1d0000fa +:10029800be1d0000be1d0000be1d0000be1d0000ea +:1002a800be1d0000be1d0000be1d0000be1d0000da +:1002b800be1d0000be1d0000be1d0000be1d0000ca +:1002c800be1d0000be1d0000be1d0000be1d0000ba +:1002d800be1d0000be1d0000be1d0000be1d0000aa +:1002e800be1d0000be1d0000be1d0000be1d00009a +:1002f800be1d0000be1d0000be1d0000be1d00008a +:10030800be1d0000be1d0000be1d0000be1d000079 +:10031800be1d0000be1d0000be1d0000be1d000069 +:10032800be1d0000be1d0000be1d0000be1d000059 +:10033800be1d0000be1d0000be1d0000be1d000049 +:10034800be1d0000be1d0000be1d0000be1d000039 +:10035800be1d0000be1d0000be1d0000be1d000029 +:10036800be1d0000be1d0000be1d0000be1d000019 +:10037800be1d0000be1d0000be1d0000be1d000009 +:10038800be1d0000be1d0000be1d0000be1d0000f9 +:10039800be1d0000be1d0000be1d0000be1d0000e9 +:1003a800be1d0000be1d0000be1d0000be1d0000d9 +:1003b800be1d0000be1d0000be1d0000be1d0000c9 +:1003c800be1d0000be1d0000be1d0000be1d0000b9 +:1003d800be1d0000be1d0000be1d0000be1d0000a9 +:1003e800be1d0000be1d0000be1d0000be1d000099 +:0803f800be1d0000be1d000047 +:020000040000fa +:100570000800fa0010002000000f78000000eb00d7 +:10058000200798000000eb00100798000d003700ce +:10059000706a80001e0060000000e000030032006e +:1005a0001e00900020079800090037001e00780008 +:1005b00000004000000f78001e0090000000e800de +:1005c000100798001e009000e90f5000f0ff340063 +:1005d0002e0090004200dd008080e800a0d12000c5 +:1005e00000804000100078000000e00009003200a8 +:1005f0002e0090004200dd008080e800a0d12000a5 +:1006000000804000100078000080e900300798006a +:10061000020037000000eb00300798003e00900019 +:10062000606a88000080fa00000006000200fa00fc +:10063000000f78001e00780030189000e70f50007f +:1006400002003a001e007800a50807001e0078008e +:1006500030189000e70f5000040032001e007800b0 +:1006600030189000e60f500002003a001e0078009b +:10067000b80807000080fa00000006000200fa0037 +:10068000000f78001e007800201890000000e000a5 +:10069000020032000040da00000000001e00780076 +:1006a000740807001e007800860407000080fa0026 +:1006b000000006000600fa001007980021079800c5 +:1006c0002e009000000f78008080eb001e00780064 +:1006d000020007000080fa00000006000400fa0093 +:1006e000000f7800110798009e0090001e0078000f +:1006f0000e0407001e007800060007000000e0005e +:1007000002003a001e007800470307000080fa004c +:10071000000006000400fa00000f78001e007800b8 +:10072000201890004200de00610060001007980071 +:100730001e0090000000e0000200320010002000c7 +:10074000100798001e0090000080fa0000000600cc +:100750001a00fa0050079800610798007207980085 +:10076000030f9800140f9800250f9800360f98007b +:100770000080eb00400798007e009000e90f5000d9 +:1007800008003a003e0890000000d10061006000bf +:100790000000e00003003a00b0ff2f00400f980077 +:1007a000860037007e0090000000e0001400350055 +:1007b0007e009000e90f500011003c009e08900060 +:1007c00030022000808f50000d0034006e00900039 +:1007d0000000e0000a0032005e0090000000e0002f +:1007e000070032000e0890000000e0000400320014 +:1007f0005e009000820007000000e000030032006d +:10080000b1ff2f00410f98006c0037000000eb0093 +:1008100030079800890b0700200798002e009000f1 +:10082000e10f5000060032002e0090000000e000b2 +:1008300003003200d0ff2f00400f98005f00370008 +:100840002e009000e10f500002003a00a40e0700b5 +:10085000400798005e009000ee0090004110980064 +:100860005e009000ae089000511098009e08900025 +:100870000e089000cc0c0700800078005e0090000d +:10088000211098005e0090009e08900031109800a2 +:100890005e009000fe00900061109800de00900065 +:1008a0000000eb00a01898005e01900090f62c006c +:1008b000b17a24000019980011199800de00900008 +:1008c0000000eb00b0189800de0090000000eb0084 +:1008d000c0189800de0090000000eb00b0089800ff +:1008e0000000eb00100798000e089000000f780041 +:1008f000070037009e007800d0ee2f0080087800b7 +:100900001e8fe8001e0090000000e800100798000d +:100910009e0090001e089000808f5000f5ff35006b +:100920005e0090000080e8003f0d07005e00900030 +:10093000660040005e019000a13520009d0907007f +:100940005e009000270007005e0090001e00070078 +:100950005e009000db0307005e009000f80040009e +:1009600020d420005f0d0700306a80000000e800fe +:10097000306a88003e089000610060000004e000da +:10098000020032005e0090000f0407002e0090006d +:10099000e10f500007003a004e009000e10f4000c8 +:1009a00002003a000040da00000000004e00900013 +:1009b000510e0700be009000410f98004e089000b5 +:1009c0000080fa00000006000200fa00000f780024 +:1009d000010220001e804000130d07000080fa0075 +:1009e000000006000200fa00000f78009e00780068 +:1009f0007c8040000c0d07000080fa00000006001b +:100a00000400fa00000f78001e0078000019900022 +:100a1000901990000000eb001007980090f62c0051 +:100a2000b17a2400800f5100818f590002003a00f2 +:100a300010002000100798001e0090000080fa00af +:100a4000000006000600fa00200798002e00900023 +:100a500067000700100798001e0090000000e000eb +:100a600025003a00570007000000e00003003a00ac +:100a7000d0ff2f00100798001f0037000080eb0008 +:100a8000000f7800160e0700000f78002e0090006f +:100a900020ff07000000e00004003a002e00900054 +:100aa000390007000000e00003003200c0ff2f0003 +:100ab00010079800080037002e009000240007005f +:100ac0000000e000020032002e00900086020700c5 +:100ad0002e009000510307000080eb009e0f1000d5 +:100ae00002003a000040da00000000001e0078001a +:100af000010e0700030007001e0090000080fa00ae +:100b0000000006000000fa00050007000000e000f9 +:100b100001003200bd0d07000080fa000000060051 +:100b20000200fa00516a8000606a80000001eb0058 +:100b3000020f7800808f5000020032001000200069 +:100b4000000f78001e0078000080fa000000060008 +:100b50000400fa00000f78001e00780020189000b2 +:100b600061006000100798001e0090000000e00087 +:100b70000200320010002000100798001e009000b4 +:100b80000080fa00000006000400fa00000f780060 +:100b90001e007800201890004300de006100600015 +:100ba000100798001e0090000000e00002003200d4 +:100bb00010002000100798001e0090000080fa002e +:100bc000000006000200fa009c0a07008000eb000b +:100bd000010f7800e10f500002003a0010002000e1 +:100be000000f78001e0078000080fa000000060068 +:100bf0000400fa00100798000000eb00000f7800d6 +:100c00001e0090000000e00003003a00b0ff2f003b +:100c1000000f7800060037001e00900078ff0700e4 +:100c20000000e00002003a0090ff2f00000f780063 +:100c30001e0078000080fa00000006000600fa009e +:100c4000200798002e009000e9ff07001007980089 +:100c50001e0090000000e00021003a00d9ff0700cc +:100c60000000e00003003a00d0ff2f0010079800ba +:100c70001b0037000080eb00000f7800980d070084 +:100c8000000f78002e009000a2fe07000000e00098 +:100c900003003a00c0ff2f0010079800080037003b +:100ca0002e009000ef0207002e0090000f000700ba +:100cb0000000e00002003a002e009000da01070078 +:100cc0000080eb009e0f100002003a000040da00a6 +:100cd000000000001e007800870d070089ff070054 +:100ce0001e0090000080fa00000006000400fa00d8 +:100cf000000f78001e007800201890000000d1003e +:100d000061006000100798001e0090000000e000e5 +:100d10000200320010002000100798001e00900012 +:100d20000080fa00000006000800fa002007980082 +:100d3000310798002e009000be009000e00f500098 +:100d4000e08f580003003a000080eb001007980085 +:100d50001a0037009bff07000000e00003003a0084 +:100d6000d0ff2f0010079800140037000080eb0020 +:100d7000000f78005a0d0700000f78002e01900038 +:100d8000be019000110020000000eb000e000700e3 +:100d90000080eb009e0f100002003a000040da00d5 +:100da000000000001e007800530d070055ff0700eb +:100db000506a8000c0189000110798001e00900033 +:100dc0000080fa00000006000800fa00000f78001a +:100dd000110798002207980033079800506a800096 +:100de000c1010700506a80002e029000be029000f0 +:100df0001e0190009e007800110207000080fa009a +:100e0000000006000200fa00000f78004175200083 +:100e10001e007800020007000080fa0000000600b3 +:100e20000800fa0020079800310798002e00900073 +:100e30006fff0700100798001e0090000000e00000 +:100e400016003a005fff07000000e00003003a00d0 +:100e5000d0ff2f0010079800100037000080eb0033 +:100e6000000f78001e0d0700000f7800be009000f4 +:100e70002e00900001000100100798000080eb0098 +:100e80009e0f100002003a000040da00000000004f +:100e90001e007800180d07001aff07001e009000c2 +:100ea0000080fa00000006000400fa001007980015 +:100eb0000000eb00000f78001e0090008bff070081 +:100ec0000000e000080032001e0090003018900082 +:100ed000e10f500004003a008000eb001e0090007b +:100ee000fefd070002003700c0ff2f00000f780052 +:100ef0001e0078000080fa00000006000200fa00e0 +:100f0000000f7800417520001e00780002000700e5 +:100f10000080fa00000006000800fa002007980090 +:100f2000310798002e00900031ff0700100798004d +:100f30001e0090000000e00016003a0018000700b4 +:100f40000000e00003003a00d0ff2f0010079800d7 +:100f5000100037000080eb00000f7800e00c070065 +:100f6000000f7800be0090002e00900001000100ec +:100f7000100798000080eb009e0f100002003a005e +:100f80000040da00000000001e007800da0c0700c4 +:100f9000dcfe07001e0090000080fa000000060042 +:100fa0000200fa00a50907008000eb00010f78009d +:100fb000e20f500002003a0010002000000f7800fd +:100fc0001e0078000080fa00000006000200fa000f +:100fd000000f780041ce20001e00780090ff07002f +:100fe0000080fa00000006000200fa00000f7800fe +:100ff00041ce20001e007800c7ff07000080fa00e5 +:10100000000006000200fa00000f780001812000b5 +:101010001e00780082ff07000080fa000000060032 +:101020000400fa00100798000000eb00000f7800a1 +:101030001e0090002dff07000000e00004003200b9 +:1010400071ff2f001e009000a4fd07000200370072 +:10105000c0ff2f00000f78001e0078000080fa000b +:10106000000006000200fa00000f78000181200055 +:101070001e007800a8ff07000080fa0000000600ac +:101080000600fa0020079800cefe07000000e000ee +:10109000110032000080eb00000f7800900c070078 +:1010a000000f7800506a8000100798001e00900022 +:1010b0000d0107001e00900070fd07002e0090003b +:1010c000610060000004e000020032001e00900099 +:1010d00003000700470c07000080fa00000006002c +:1010e0000400fa00100798000000eb00000f7800e1 +:1010f0001e009000a4fe07000000e00003003a007c +:10110000c0ff2f00000f78000a0037001e0090007b +:1011100078004000b90b0700306a80000000e90049 +:10112000306a88001e0190006000b8000019980025 +:10113000111998001e0078000080fa0000000600d7 +:101140000600fa00200798002e009000a8fe070075 +:10115000100798001e0090000000e00036003a00e2 +:1011600098fe07000000e00003003a00d0ff2f00c7 +:1011700010079800300037000080eb00000f780067 +:10118000570c0700000f78002e0090007efe07002d +:101190000000e00003003200c0ff2f00100798009d +:1011a0001d003700516a80002e009000808f500093 +:1011b00003003a00d0ff2f001007980016003700f8 +:1011c0002e00900062fe07000000e00003003200e5 +:1011d0002e009000c4000700070037002e0090008a +:1011e000c2fe07000000e000030032008000eb00b8 +:1011f0002e0090004d0107002e00900045fd0700d5 +:101200000000e000020032002e009000950107006f +:101210002e00900019fd07000080eb009e0f1000cb +:1012200002003a000040da00000000001e007800d2 +:10123000310c070033fe07001e0090000080fa000a +:10124000000006000600fa00200798002e0090001b +:1012500067fe0700100798001e0090000000e000e5 +:1012600014003a0057fe07000000e00003003a00b7 +:10127000d0ff2f00100798000e0037000080eb0011 +:10128000000f7800160c0700000f78002e00900069 +:1012900093ff0700100798000080eb009e0f1000de +:1012a00002003a000040da00000000001e00780052 +:1012b000110c07001e0090000080fa0000000600dc +:1012c0000800fa0020079800310798002e009000cf +:1012d00047fe0700100798001e0090000000e00085 +:1012e00015003a0037fe07000000e00003003a0056 +:1012f000d0ff2f00100798000f0037000080eb0090 +:10130000000f7800f60b0700000f78002e00900009 +:10131000a01890003e009000010878000080eb00cb +:101320009e0f100002003a000040da0000000000aa +:101330001e007800f00b07001e0090000080fa00ed +:10134000000006000800fa00200798003107980006 +:101350002e00900026fe0700100798001e00900047 +:101360000000e0002d003a003e0090000000e00088 +:10137000030035003e009000e80f500003003400e9 +:10138000b0ff2f0010079800240037000dfe070063 +:101390000000e00003003a00d0ff2f001007980083 +:1013a0001e0037000080eb00000f7800cc0b070018 +:1013b000000f78003e0090000000e00003003a00bb +:1013c0002e009000e0109000310798000000eb0024 +:1013d000100798002e009000ebfd07000000e000d1 +:1013e00003003200c0ff2f001007980003003700f1 +:1013f000be0090002e009000a50107000080eb00c9 +:101400009e0f100002003a000040da0000000000c9 +:101410001e007800b80b0700bafd07001e00900000 +:101420000080fa00000006000400fa00100798008f +:101430001e009000201890000000e0000200320022 +:101440000040da00000000001e009000f010900044 +:10145000010f78001e009000201890008000780096 +:101460000100a0001e009000211898001e009000ae +:101470000080e8009e00780008000700606a800095 +:10148000701090009e0f5000020034001e0090006b +:10149000606a88000080fa00000006000400fa007c +:1014a000000f7800110798001e0090004200dd0038 +:1014b00080007800a0d12000008040009e007800cd +:1014c000880a0700110020001e0090000008dd00bf +:1014d00080007800706a800000807000706a880068 +:1014e0000080fa00000006000600fa0010079800cd +:1014f0001e00900020189000e10f50000200320002 +:101500000040da00000000009e00900080d520001e +:10151000808f500002003a000040da000000000016 +:101520001e009000f0109000010f78001e00900047 +:10153000a0189000e0ff2f00808060001e00900047 +:10154000211898001e0090000080e8009e0078009e +:10155000220007000000e0000200320004fc070047 +:1015600019003700616a80001e009000808f5000d3 +:1015700015003a001e0078004200dd008080e8007f +:10158000a0d1200000804000100078000000e000a2 +:10159000090032001e0078004200dd008080e80073 +:1015a000a0d1200000804000100078000080e900f9 +:1015b00020079800020037000000eb002007980089 +:1015c000ae009000616a88001e0090000080e80074 +:1015d000150a07000080fa00000006000600fa0065 +:1015e00010079800210798001e009000830a07004a +:1015f0002e0090004200dd0080007800a0d1200085 +:1016000000804000130a0700000f78001e00e00071 +:1016100008003200110020002e0090000008dd00bc +:101620000080ea0080007800706a8000008060001e +:10163000706a88001e0078000080fa000000060032 +:101640000a00fa00000f780011079800220798009e +:1016500034079800450798001e007800a0189000f5 +:10166000b0ff2f00008060000000e00003003200a7 +:101670000040da00000000000f0037003e0090003c +:10168000ce009000e00f5000e08f580003003a00b9 +:101690000040da0000000000070037009e007800dc +:1016a00066804000710607000000e0000200320082 +:1016b0000040da00000000001e00780020189000b2 +:1016c000800078000110a0001e007800211898000a +:1016d0001e007800ae009000311898009e0078003f +:1016e000212090000010a000a02098001e00900073 +:1016f0000000e000060032009e80e8001e0090001e +:10170000f80907001e0078009e009000310898003c +:101710009e007800668040003e019000ce0190005f +:10172000cc0507000080fa00000006000800fa005f +:10173000000f7800110798001e007800a018900094 +:1017400090ff2f00008060000000e00006003a00db +:101750001e007800201890000000d1006100600099 +:101760000000e00002003a000040da000000000043 +:101770001e80e800b7090700300798001e007800b7 +:10178000300890008000eb00210798000000e00086 +:1017900002003a001000200020079800be009000d0 +:1017a0002e009000808f5000020032000040da00ce +:1017b000000000001e80e800100a07001e80e800fc +:1017c000990907001e00780098fb07009e0078002a +:1017d0000000eb00b00898001e0078009e0090000a +:1017e000411898009e00780066804000de050700e2 +:1017f0001e007800a0189000d0ff2f0080806000ad +:101800001e007800211898009e0078000000eb0070 +:10181000b01898000080fa00000006000200fa00ec +:10182000000f78001e007800a0189000d0ff2f0055 +:10183000008060000000e000020032000040da009a +:10184000000000001e007800201890008000780042 +:101850000120a0001e007800211898000080fa00e6 +:10186000000006000200fa00000f78001e00780059 +:10187000a018900090ff2f00008060000000e000a2 +:1018800006003a001e007800201890004200de009a +:10189000610060000000e00002003a000040da0051 +:1018a000000000001e007800a0189000b0ff2f007c +:1018b000808060001e007800211898000080fa00e7 +:1018c000000006000200fa00000f78001e007800f9 +:1018d000201890000000e000030032000040da0011 +:1018e000000000000f0037009e0078007c80400060 +:1018f000580907000000e00003003a000040da0049 +:101900000000000007003700010220001e80400098 +:10191000500907000000e00002003a000040da0031 +:10192000000000001e007800e01090001e0078000b +:10193000711098001e007800201890008000780038 +:101940000130a0001e007800211898009e00780049 +:101950000000eb00d01898000080fa00000006009c +:101960000200fa00000f78001e0078002018900096 +:10197000e80f5000020032000040da0000000000d2 +:101980001e007800501190001e007800a0109000fa +:101990001e00780040109000890807008000780041 +:1019a0001e007800010878001e007800a018900042 +:1019b00070ff2f00808060001e00780021189800c2 +:1019c0000080fa00000006000400fa0010079800ea +:1019d0000000eb00000f78001e0090006afc07007a +:1019e0000000e000050032001e009000dcff070050 +:1019f0001e0090008cfe070002003700c0ff2f0081 +:101a0000000f78001e0078000080fa000000060039 +:101a10000e00fa002007980031079800420798004e +:101a200053079800640798000000eb001007980027 +:101a30002e009000070907000000e00011003a00a6 +:101a40002e009000100090000080e900000f780048 +:101a50004e0090000000e00005003200ce01900032 +:101a60006e019000de0090001e007800030001006f +:101a7000be0090001e00780018fb07001000200038 +:101a8000100798001e0090000080fa000000060079 +:101a90000400fa00000f7800110798001e0078007b +:101aa0002bfc07000000e000040032009e009000c4 +:101ab0001e00780006000700030037001e007800b3 +:101ac0009e009000711098000080fa00000006004f +:101ad0000400fa00000f7800110798001e0078003b +:101ae0001bfc07000000e00002003a000040da00a2 +:101af000000000001e007800f01090001e80e8003a +:101b0000b6fe07001e0078009e009000711098003d +:101b10001e80e8009e00900060fe070094fa070017 +:101b20000080fa00000006000800fa002007980074 +:101b3000310798000000eb00100798002e0090007d +:101b40007008900064005000000f78000a00370011 +:101b50003e0090009e0f100003003a00100020008d +:101b6000100798000a0037001e007800300090002f +:101b700064005000000f78009e00780064804000f0 +:101b8000ae009000fc804000810f5000f0ff3a0052 +:101b90001e0090000080fa00000006000600fa0017 +:101ba000200798002e009000e01090001107980088 +:101bb0002e0090007008900064005000000f780024 +:101bc000080037009e0090001e00780015000700f6 +:101bd000100798001e00780030009000640050004c +:101be000000f78009e00780064804000ae009000f6 +:101bf000fc804000810f5000f2ff3a002e00900060 +:101c0000f01090001e009000808f50000300320002 +:101c10009e0090002e0090009dff07000080fa00bb +:101c2000000006000800fa0010079800210798003d +:101c30002e009000000f78001e00900060009000c1 +:101c400030079800be009000e18f50000400320081 +:101c50003e009000e20f5000090032000d003700f6 +:101c60001e009000000890009e0f50000b003d00e9 +:101c70001e00900080089000010f780007003700d8 +:101c80009e0078001e00900007000700000f7800fb +:101c9000020037000040da00000000001e0078005b +:101ca0000080fa00000006000800fa0020079800f3 +:101cb000310798003e009000100798002e00900019 +:101cc000100090000080e900000f78000c00370041 +:101cd0001e007800f01090001e009000808f5000d1 +:101ce00003003d001e007800f010900011079800de +:101cf0001e007800200090000080e900000f7800ae +:101d00009e80e8002e009000808f5000f0ff3a0087 +:101d10001e0090000080fa00000006000800fa0093 +:101d200020079800310798002e009000f0009000e6 +:101d3000110798001e00900030189000e70f500027 +:101d4000060032001e00900030189000e60f500090 +:101d5000020032000040da00000000001e00900087 +:101d600030089000000f78001e0090000102200053 +:101d7000808040003e0090000002b000590807003b +:101d80001e007800e80040002e009000680040002f +:101d9000420807009e0078003e00900062ff0700a6 +:101da0000000e00003003a009e0078002107980040 +:101db000ddff37000080fa00000006000800fa008e +:101dc00020079800310798002e009000d000900066 +:101dd000110798001e00900090009000010f7800fd +:101de000090037001e009000840807001e009000c4 +:101df0000d0807001e007800100798001e009000d4 +:101e000090009000010f78002e009000e800400044 +:101e10001e009000808f5000f2ff3a003e009000bc +:101e200090109000110798001e0090009000900004 +:101e3000010f7800090037001e0090006f080700ae +:101e40001e009000f80707001e0078001007980099 +:101e50001e00900090009000010f78003e0090005e +:101e600001022000808040001e009000808f500002 +:101e7000f1ff3a000080fa00000006000800fa00b6 +:101e800020079800310798002e009000f000900085 +:101e9000110798003e009000200007000000e000bd +:101ea0001c0032001e00900030189000e70f500018 +:101eb000040032001e00900030189000e60f500021 +:101ec00014003a001e00900030089000000f7800c7 +:101ed0009e0078003e00900013ff07000000e00025 +:101ee000090032003e00900030089000be009000d3 +:101ef0008aff07003e019000ae0090001000200015 +:101f000041060700030037001e00780020079800f4 +:101f1000ddff37000080fa00000006000400fa0030 +:101f2000000f78001e007800201890000000d100fb +:101f300061006000100798001e0090000000e000a3 +:101f40000200320010002000100798001e009000d0 +:101f50000080fa00000006000400fa00000f78007c +:101f6000110798009e00780068804000b9070700bc +:101f70000000e0000e003a001e0090000002b000d9 +:101f8000b40707000000e000020032000040da0061 +:101f9000000000001e0190009e0078000000eb0091 +:101fa000190607009e0090001e00780083ff0700be +:101fb0000080fa00000006000400fa0010079800f4 +:101fc0009e0090000000eb00900898001e0090001a +:101fd00064004000090807001e0090007000900097 +:101fe000eefe07001e0090009a0707000000e000c8 +:101ff000040032009e0090000000eb00f00098000a +:10200000150037001e009000100090000080e900cd +:10201000000f78001e009000f0009000212090003a +:102020000000a000a02098008000eb001e007800b7 +:10203000290007001e00900070019000a22090006f +:10204000e0ff2f0000806000202198009e007800b3 +:102050001e009000020007000080fa000000060049 +:102060000600fa0010079800210798001e00900053 +:10207000ae009000710098001e00900010089000c3 +:102080008000e8001e009000110898001e009000db +:10209000e40040002e0090007c0040009107070003 +:1020a0002e009000f01090001e009000ddfe070052 +:1020b000000f78002e009000701090009e0f5000ce +:1020c000030032009e0078002e00900070fe070092 +:1020d0000080fa00000006000400fa00000f7800fb +:1020e000110798009e0090001e0078008ffd0700e9 +:1020f0001e007800060007000000e00002003a0021 +:102100001e007800c8fc07000080fa0000000600ee +:102110000400fa00000f78001e00780020189000dc +:102120004200de0061006000100798001e00900071 +:102130000000e000020032001000200010079800ac +:102140001e0090000080fa00000006000800fa005f +:102150001007980021079800320798003e01900070 +:10216000ae0090001e0090001f000700000f7800d6 +:102170001e00e00019003a001e0090002a07070028 +:102180001e00900064004000270707001e0090001a +:1021900068004000240707001e009000ae00900079 +:1021a000610098009e0090000000eb00f000980095 +:1021b0001e009000be009000010898009e00900054 +:1021c0000000eb00900898001e01900050e42900e8 +:1021d0002171210020099800310998001e00780023 +:1021e0000080fa00000006000800fa0010079800be +:1021f00021079800320798000000eb00000f7800dc +:102200001e0090000000e00003003a00b0ff2f0025 +:10221000000f78001b0037001e0090001c00070014 +:102220000000e00003003200b0ff2f00000f780034 +:10223000140037002e009000e10f5000060032001d +:102240002e009000e20f500003003200b0ff2f007c +:10225000000f78000b0037002e009000e10f5000b7 +:1022600008003a003e0090000000e0000300350046 +:102270003e009000e80f500002003400b0ff2f0035 +:10228000000f78001e0078000080fa0000000600b1 +:102290000400fa00000f78001e007800200990006a +:1022a000b00990000000eb001007980050e42900ee +:1022b00021712100800f5100818f590002003a00e6 +:1022c00010002000100798001e0090000080fa0007 +:1022d000000006000600fa00200798002e0090007b +:1022e00052000700100798001e0090000000e00058 +:1022f0002d003a00420007000000e00003003a0011 +:10230000d0ff2f0010079800270037000080eb0057 +:10231000000f7800f2070700000f78002e009000f1 +:10232000700090000000e000080032002e009000d5 +:10233000f0009000506a8000808f5000030032004f +:10234000a0ff2f00100798000f0037002e0090000c +:10235000d80407002e009000700090000000e000fc +:10236000050032002e00900013ff07002e009000a1 +:1023700064004000ac0607002e0190006000b80029 +:1023800020099800310998000080eb009e0f100092 +:1023900002003a000040da00000000001e00780051 +:1023a000d5070700030007001e0090000080fa0018 +:1023b000000006000000fa00050007000000e00031 +:1023c00001003200910707000080fa0000000600bb +:1023d0000200fa00516a8000606a80000001eb0090 +:1023e000020f7800808f50000200320010002000a1 +:1023f000000f78001e0078000080fa000000060040 +:102400000200fa008d0407008000eb00010f780045 +:10241000e10f500002003a0010002000000f780089 +:102420001e0078000080fa00000006000400fa0098 +:10243000100798000000eb00000f78001e009000cd +:102440000000e00003003a00b0ff2f00000f78000a +:10245000060037001e0090008dff07000000e0001e +:1024600002003a0090ff2f00000f78001e00780055 +:102470000080fa00000006000c00fa003007980007 +:1024800042079800530798003e009000e7ff0700be +:10249000200798000000eb00100798002e00900025 +:1024a0000000e00050003a00d5ff07000000e00007 +:1024b00003003a00d0ff2f00200798004a003700a1 +:1024c0000080eb00000f780085070700000f780000 +:1024d0003e009000f0009000506a8000808f500015 +:1024e00008003a003e009000100890008000e800cc +:1024f0003e009000110898000000eb0020079800b3 +:10250000230037003e00900060009000e10f500073 +:1025100009003a00506a8000e01090003e009000f0 +:1025200000089000808f500003003d00a0ff2f00a6 +:1025300020079800160037003e00900070009000c1 +:102540000000e00004003a00516a80003e00900064 +:10255000c3fe07000e0037004e009000de00900022 +:10256000e00f5000e08f580003003a000080eb00bd +:1025700020079800060037004e019000de01900011 +:102580003e0090001b00070010002000100798007c +:102590008fff07000000e00005003a001e009000d9 +:1025a0000000e000020032000040da0000000000fd +:1025b0000080eb009e0f100002003a000040da009d +:1025c000000000001e0078004b07070079ff07009d +:1025d0001e0090000000e00003003200506a8000fe +:1025e000c0189000210798002e0090000080fa008b +:1025f000000006000800fa00100798002207980063 +:10260000330798001e00900060009000e20f500019 +:102610000f003a00506a8000f01090001e009000f9 +:102620007000900070109000808f500005003d00f9 +:10263000506a8000f01090001e0090007000900022 +:102640001e00070070002000000f78000200370015 +:1026500060002000000f78001e0090002e01900006 +:10266000be0190009e00780005000700516a8000be +:102670001e00900001fe07000080fa000000060026 +:102680000800fa00000f7800110798002207980050 +:1026900033079800506a800093fb0700506a80005f +:1026a0002e029000be0290001e0190009e00780055 +:1026b000e3fb07000080fa00000006000400fa00b7 +:1026c000000f7800110798001e007800f0109000ad +:1026d0001e009000808f5000180034001e0078000b +:1026e000180007000000e000040032009e00900087 +:1026f0001e007800f6fc0700100037001e0078006e +:102700009e009000711098001e00780003fe0700e4 +:102710000000e000090032001e0078003018900030 +:10272000e70f500005003a001e00780030089000c6 +:10273000f0009000010f7800e3ff37000080fa00fe +:10274000000006000400fa00000f78001e00780068 +:102750002018900061006000100798001e00900093 +:102760000000e00002003200100020001007980076 +:102770001e0090000080fa00000006000200fa002f +:10278000000f78006011b8001e0078003aff0700c3 +:102790000080fa00000006000600fa0020079800fa +:1027a0002e00900021ff0700100798001e009000e7 +:1027b0000000e0002c003a0011ff07000000e000dc +:1027c00003003a00d0ff2f001007980026003700c2 +:1027d0000080eb00000f7800c1060700000f7800b2 +:1027e0002e009000f0009000506a8000808f500012 +:1027f00003003200a0ff2f001007980012003700de +:102800002e009000100890008000e9002e0090003b +:10281000110898002e009000100890000000e000c1 +:1028200009003c002e009000100890000000e0001d +:1028300003003d000040da00000000000200370005 +:102840002e009000dcfd07000080eb009e0f1000c2 +:1028500002003a000040da00000000001e0078008c +:10286000a5060700d3fe07001e0090000080fa00b6 +:10287000000006000600fa00200798002e009000d5 +:102880007008900064005000100798001e0090002f +:102890003000900064005000000f780008003700fe +:1028a0001e009000c4fd07001e007800100798006d +:1028b0001e0078003000900064005000000f780087 +:1028c0001e009000e40040002e0090007c004000bc +:1028d000808f5000f2ff3a000080fa0000000600ee +:1028e0000200fa00000f78001e00780030189000f7 +:1028f000e70f5000020032000040da000000000044 +:102900001e00780020209000610060000000e000c0 +:102910000e003a001e00780030089000f000900091 +:10292000010f78001e0078009cfc07001e00780054 +:102930007afd07000000e000040032001e0078006d +:1029400030189000e70f5000f2ff32000080fa00cc +:10295000000006000200fa00000f78001e00780058 +:10296000300890009e0078007bfd07000080fa0090 +:10297000000006000800fa001007980021079800e0 +:1029800032079800ae0090001e0090000b00070078 +:10299000000f78001e00e00005003a003e019000a4 +:1029a000ae0090001e00900082010700000f78002a +:1029b0001e0078000080fa00000006000600fa0001 +:1029c00010079800210798000000eb00000f780026 +:1029d0001e0090000000e00003003a00b0ff2f004e +:1029e000000f7800060037001e0090000700070067 +:1029f0000000e00002003200b0ff2f00000f78005e +:102a00001e0078000080fa00000006000400fa00b2 +:102a1000000f78001e00780060019000f001900027 +:102a20000000eb0010079800c0fb270031a9290027 +:102a3000800f5100818f590002003a0010002000e1 +:102a4000100798001e0090000080fa0000000600a9 +:102a50000600fa00200798002e00900011000700e1 +:102a6000000f78001e00e0000b003a001c06070073 +:102a7000100798002e0090003b010700000f78001f +:102a80002e0190006000b80060019800710198006c +:102a90001e009000180607001e0078000080fa0053 +:102aa000000006000400fa00100798000000eb0088 +:102ab000000f78001e0090000000e00003003a00c4 +:102ac000b0ff2f00000f7800060037001e009000b6 +:102ad000ceff07000000e00002003a0090ff2f0048 +:102ae000000f78001e0078000080fa000000060049 +:102af0000a00fa0020079800320798004307980060 +:102b00002e009000e7ff0700000f78001e00e00095 +:102b100009003a00f2050700100798003e019000f6 +:102b2000ce0190002e009000ca000700000f780030 +:102b30001e009000f00507001e0078000080fa00db +:102b4000000006000600fa00200798002e00900002 +:102b5000d4ff0700000f78001e00e00007003a00d5 +:102b6000df050700100798002e009000fe00070008 +:102b7000000f78001e009000df0507001e0078009f +:102b80000080fa00000006000a00fa002007980002 +:102b900031079800420798002e009000c1ff0700ff +:102ba000000f78001e00e00009003a00cc05070085 +:102bb000100798004e019000be0090002e0090007b +:102bc00015010700000f78001e009000ca050700dd +:102bd0001e0078000080fa00000006000800fa00dd +:102be00020079800310798002e009000adff0700e5 +:102bf000000f78001e00e00009003a00b805070049 +:102c0000100798002e00900018010700800078003f +:102c10003e009000010878001e009000b6050700f5 +:102c20001e0078000080fa00000006000800fa008c +:102c300020079800310798002e00900099ff0700a8 +:102c4000000f78001e00e00008003a00a40507000d +:102c5000100798002e009000110107003e0190001f +:102c60000089be001e009000a30507001e0078002a +:102c70000080fa00000006000200fa0020db2000bd +:102c8000690407000000eb00000f78000700370020 +:102c90001e0078004200dd008000780060db20002c +:102ca00000804000600407001e0fe8007000200054 +:102cb0009e0f1000f6ff34000080fa0000000600ae +:102cc0000a00fa00806a80006700600040079800f0 +:102cd0004e0090000000e00041003a00a06d80002e +:102ce000300798003e0090001000900020079800e8 +:102cf000370037003e00900040019000d001900066 +:102d0000f0ff2f0001002000800f5100818f59003b +:102d1000080032003e00900040019000d001900079 +:102d20007000200001002000800f5100818f5900a9 +:102d300002003e000040da00000000003e0090006b +:102d4000d00090004000900068005000e0805800e3 +:102d50003e01900040019800510198003e00900013 +:102d600040019000d0019000700020000100200080 +:102d7000800f5100818f590010003e003e009000ee +:102d80009e0407003e0190003e009000d00090009d +:102d90004000900080007800806a80000080400041 +:102da000670060004200dd008000780060db2000ea +:102db00000804000820078004a0407002e00900046 +:102dc000300798002e009000100090002007980017 +:102dd000be00900020db2000808f5000c5ff3a002d +:102de0004e0090004200dd008000780060db200093 +:102df000008f40000b0037001e007800100090008c +:102e0000100798001e009000570007001e00900059 +:102e1000200190001e009000b00090001e00900065 +:102e2000020001001e0078000a0407000000e00014 +:102e3000f1ff32001e007800060407000000e000e9 +:102e400002003a000040da00000000000080fa00b2 +:102e5000000006000a00fa002007980032079800d8 +:102e6000430798000000eb00100798003e01900017 +:102e7000ce019000f0ff2f0001002000800f5100d4 +:102e8000818f5900050032003e009000ce00900076 +:102e9000e00f5000e08f580003003a00b0ff2f0011 +:102ea000100798002d0037002e0090002e0007001c +:102eb000100798003e019000ce01900070002000a5 +:102ec00001002000800f5100818f590012003e0048 +:102ed000be009000806a800000804000670f6000a4 +:102ee0001e007800cf80de002e0190004001980087 +:102ef000510198002e0190001e0078004200dd0074 +:102f00008000780060db20000080400082007800b4 +:102f1000f403070011003700806a800001002000e0 +:102f2000670160006000b80003002000020070002c +:102f3000838070003e019000ce01900000004100af +:102f4000818049002e0190004001980051019800b5 +:102f5000ae00900020db2000e20307001e0090007e +:102f60000080fa00000006000400fa001007980034 +:102f70000000eb00000f78001e0090003b000700ef +:102f80000000e000080032001e0190006000b80060 +:102f900040019800510198001e009000170407009e +:102fa0001e009000a00307001e0078000080fa00b9 +:102fb000000006000800fa0010079800210798009a +:102fc000320798003e019000ae0090001e00900075 +:102fd00011000700000f78001e00e0000b003a000f +:102fe0001e009000900307001e0190006000b800d2 +:102ff00040019800510198001e019000c0fb27007d +:1030000031a9290060019800710198001e00780024 +:103010000080fa00000006000800fa00100798007f +:1030200021079800320798000000eb00000f78009d +:103030002e0090000000e00003003a00b0ff2f00d7 +:10304000000f7800060037001e009000ae009000d0 +:10305000210098001e009000be00900031009800f2 +:103060001e0078000080fa00000006000400fa004c +:10307000000f78001e007800760307008000eb0048 +:10308000110798000000e00002003a001000200044 +:10309000100798001e0090000080fa000000060053 +:1030a0000800fa00300798006000b8001007980088 +:1030b000210798003e009000ecff07000000e000b0 +:1030c0002a003200806a8000670f60003e00900096 +:1030d00040019000d00190001e007800cf80de00fb +:1030e000800f5100818f59000a0036003e00900089 +:1030f00040019000d00190001e007800cf80de00db +:1031000000005100818059001007980021079800a5 +:10311000160037003e00900040019000d001900062 +:103120001e007800cf80de00800f5100818f590093 +:103130000c0031003e00900040019000d001900052 +:103140001e007800cf80de00000051008180590011 +:1031500068004000e08048001007980021079800b0 +:10316000020037000040da00000000001e0090005e +:10317000ae0090000080fa00000006000200fa0095 +:10318000000f7800c06e800000000100fdff3700d6 +:103190001000fa00200798003107980042079800b5 +:1031a0005307980064079800750798000000eb002b +:1031b000100798000f0037001e0090004200dd004d +:1031c00080007800a0d12000008040001603070096 +:1031d0001e00900080004000e0d920008080400068 +:1031e0000000eb00800878001e0090000000e8005e +:1031f000100798001e009000e90f5000eeff340009 +:1032000020d42000080307000000eb00306a88008b +:103210000000eb00406a88000000eb00706a880044 +:103220000000eb00806a88000000eb00906a8800d4 +:103230000000eb00606a88000000eb00506a880024 +:103240007e009000c06e88000000eb001007980020 +:103250000a0037001e009000000040008000780047 +:103260004e00900080804000d0ee2f008008780053 +:103270001e0090000000e800100798009e009000db +:103280005e009000808f5000f2ff3900de00900059 +:103290004e00900044020700b06a880076fe0700e6 +:1032a000be0090002e00900018000700000f78006c +:1032b0001e00e000020032000040da0000000000c2 +:1032c00080d52000606a880080d52000bef9070004 +:1032d000000f78001e00e000020032000040da001b +:1032e0000000000080d52000506a88006e00900029 +:1032f00000000100406a80000000a000406a8800d1 +:10330000bc0307000080fa00000006000400fa0079 +:10331000000f7800110798001e0090002600200082 +:103320008002eb00000278009e01780092002000ed +:10333000e18b210080d5200005f507000080fa0010 +:10334000000006000400fa000000eb0010079800df +:10335000680007000000e00003003a00d0ff2f00e3 +:1033600010079800110037000080eb00000f780074 +:10337000db030700000f7800806a80000000e8008f +:10338000806a88001f0007004dfe07000080eb00e8 +:103390009e0f100002003a000040da00000000001a +:1033a0001e007800d4030700030007001e009000f1 +:1033b0000080fa00000006000000fa000500070087 +:1033c0000000e00001003200900307000080fa00d6 +:1033d000000006000200fa00516a8000606a800066 +:1033e0000001eb00020f7800808f500002003200d5 +:1033f00010002000000f78001e0078000080fa0006 +:10340000000006000600fa00506a8000701090006c +:10341000200798002e00900080004000e0d9200096 +:1034200000804000100078000000e0002f00320013 +:10343000516a8000511890000000e800d0189800f0 +:10344000506a800050189000000178002e00900013 +:1034500080004000e0d9200000804000100078008b +:10346000800f510021003600516a80000000eb00ff +:10347000d01898002e0090004200dd0080007800f7 +:10348000a0d1200000804000000f78001e007800ce +:10349000700207000000e00014003a001e007800ef +:1034a00010009000100090009e0f50000f0032009e +:1034b0002e0090004200dd0080007800a0d12000a6 +:1034c000008040009a020700100798001e0190003b +:1034d0002e0090004200dd0080007800a0d1200086 +:1034e00000804000820078007e0207000080fa0021 +:1034f000000006000200fa00500007008000eb0008 +:10350000010f7800e20f500002003a001000200086 +:10351000000f78001e0078000080fa00000006000e +:103520000800fa0020079800310798000000eb001f +:1035300010079800280007000000e00003003a0090 +:10354000d0ff2f0010079800200037002e009000b9 +:103550000000e000090035002e009000e80f500048 +:1035600006003c003e0090000000e0000300350033 +:103570003e009000e10f400003003a00b0ff2f0032 +:1035800010079800110037000080eb00000f780052 +:1035900053030700000f78002e0090003e019000ba +:1035a00080004000e0d92000008040000208780040 +:1035b0000080eb009e0f100002003a000040da008d +:1035c000000000001e0078004b0307001e00900062 +:1035d0000080fa00000006000200fa001700070051 +:1035e0008000eb00010f7800e10f500002003a006c +:1035f00010002000000f78001e0078000080fa0004 +:10360000000006000000fa00806a80000080fa00d6 +:10361000000006000000fa00406a80000080fa0006 +:10362000000006000200fa00000f78001e0078007b +:10363000d06e88000080fa00000006000400fa0046 +:10364000406a8000610060000004e0000b0032006e +:103650002b0307000000e0000300320020002000e0 +:103660001007980002003700100020001007980093 +:103670001e009000000f7800020037000000eb00f1 +:10368000000f78001e0078000080fa00000006009d +:103690000000fa00506a80000080fa000000060076 +:1036a0000000fa00506a8000401090000080fa008c +:1036b000000006000600fa00200798002e00900087 +:1036c000100090000080e900100798001e00900094 +:1036d000200090000080e900000f7800090037000a +:1036e00081ff2f001e009000130007001e007800cd +:1036f000100798001e007800200090000080e9006c +:10370000000f78001e0090008080e8002e009000de +:10371000808f5000f2ff3a002e009000cd0107008c +:103720000000e00002003a000040da000000000063 +:103730000080fa00000006000400fa00000f780084 +:10374000110798009e0090001e007800f7f7070010 +:103750001e007800060007000000e00002003a00aa +:103760001e00780030f707000080fa000000060015 +:103770000400fa00000f78001e0078002018900066 +:103780004200de0061006000100798001e009000fb +:103790000000e00002003200100020001007980036 +:1037a0001e0090000080fa00000006000400fa00ed +:1037b00010079800406a8000000f7800416a80007e +:1037c0001e00900000807000406a88001e00780093 +:1037d0000080fa00000006000400fa0010079800bc +:1037e000406a8000000f78001e0090008080ea0090 +:1037f000406a800000806000406a88001e007800f7 +:103800000080fa00000006000600fa00000f7800b1 +:1038100011079800220798001e00e00009003200fe +:10382000b06e80000000e00002003a00200020009e +:10383000deff0700b06e80000000e800b06e880078 +:1038400008003700b06e80000000e900b06e88000c +:10385000b06e80000000e00002003a00200020006e +:10386000ddff0700d06e80000000e00005003200a0 +:10387000d36e80002e0190009e0090001e00780004 +:10388000030001000080fa00000006000800fa00b2 +:103890001007980021079800320798000000eb00fd +:1038a000000f78000b0037002e0090009000780089 +:1038b0001e009000010878001e0090000080e800c3 +:1038c000100798002e0090000080e8002007980064 +:1038d0001e0fe8009e0078003e009000808f500090 +:1038e000f1ff39000080fa00000006003600f80001 +:1038f000809fbe00829fbe00849fbe00869fbe0048 +:103900003400f80000002000a00188000200fa0046 +:103910008460a90010002000000f78001000200033 +:10392000000f780087fe07000080fa003400f900dd +:103930004f03be004f02be004f01be004f00be004d +:103940003600f900004006000200fa00000f78007f +:1039500030000700401f200001002000f2f40700a3 +:10396000fcff37000200fa00000f7800803e2000c4 +:1039700001002000ecf40700fcff37000200fa0011 +:10398000000f7800c05d200001002000e6f4070071 +:10399000fcff37000000fa000421a90004c1a900bf +:1039a00005a1a8004110200091407800f0ccb300a0 +:1039b00000c0600001c2b3000140700004e1b70024 +:1039c000301f2000100888008460a9009460a800bf +:1039d000510a200091407800f0c8b30000c0600098 +:1039e00001c2b30001407000a5e0b70005e1a800e6 +:1039f0009680a800e10a20009140780080cfb300b3 +:103a000000c060000004a000aee0b7000080fa0033 +:103a1000000006000000fa00160020008002eb0003 +:103a20004408200083a320006200200021cb210055 +:103a3000e0c8200046f30700160020008002eb00db +:103a40004408200003b4200052002000e1cb2100f4 +:103a500040cd20003ef307000080fa000000060081 +:103a60000000fa000080fa00000006000000fa00e2 +:103a7000160020008002eb00440820000393200081 +:103a80007200200041ca210080c4200030f30700ea +:103a90000080fa00000006000000fa00db000700ca +:103aa000bcff070005d3210064d32100430620009a +:103ab000828620004103200000802000b4fd070022 +:103ac000100020000080fa00000006003400f8001a +:103ad000881f780008002000a80188004f047800a3 +:103ae0000000fa000040da00000000000080fa0048 +:103af0003400f900004006003400f800881f780008 +:103b000008002000a80188004f0478000000fa0097 +:103b10000040da00000000000080fa003400f900e4 +:103b2000004006003400f800881f780008002000dc +:103b3000a80188004f0478000000fa000040da0075 +:103b4000000000000080fa003400f9000040060088 +:103b50003400f800881f780008002000a8018800c1 +:103b60004f0478000000fa000040da000000000076 +:103b70000080fa003400f900004006003400f8002c +:103b8000881f780008002000a80188004f047800f2 +:103b90000000fa000040da00000000000080fa0097 +:103ba0003400f900004006000400fa00000f78001d +:103bb000110798001e0078000080fa00000006003f +:103bc0000600fa00000f78001107980022079800fd +:103bd0001e007800800078001e0090000108780028 +:103be0001e0090000080e800100798009e009000e2 +:103bf0000000eb00800878001e0090000080e800c4 +:103c0000100798009e0090000080eb00800878006c +:103c10001e0090000080e800100798009e009000b1 +:103c200030102000800878001e0090000080e8001e +:103c3000100798009e009000404121008008780005 +:103c40001e0090000080e800100798009e00900081 +:103c500020212100800878001e0090000080e800ec +:103c6000100798009e0090003031210080087800f5 +:103c70001e0090000080e800100798009e00900051 +:103c800000012100800878001e0090000080e800fc +:103c9000100798009e009000101121008008780005 +:103ca0001e0090000080e800100798009e00900021 +:103cb00080802000800878001e0090000080e800ce +:103cc000100798009e0090009090200080087800d7 +:103cd0001e0090000080e800100798009e009000f1 +:103ce00060602000800878001e0090000080e800de +:103cf000100798009e0090007070200080087800e7 +:103d00001e0090000080e800100798009e009000c0 +:103d100040402000800878001e0090000080e800ed +:103d2000100798009e0090005050200080087800f6 +:103d30001e0090000080e800100798009e00900090 +:103d400020202000800878001e0090000080e800fd +:103d5000100798009e009000303020008008780006 +:103d60001e0090000080e800100798002e009000d0 +:103d7000800078001e009000010878001e0090006e +:103d80000080e800100798009e00900010102000ae +:103d9000800878001e0090000080e800100798005e +:103da0009e0090000000eb00800878001e0090004c +:103db0000080e800100798009e0090000000eb00d3 +:103dc000800878001e0090000080e800100798002e +:103dd0009e0090000000eb00800878001e0090001c +:103de0000080e800100798009e0090000000eb00a3 +:103df000800878001e0090000080e80010079800fe +:103e00001e0090000080fa00000006000000fa008a +:103e1000330107000080fa00000006000000fa00ed +:103e20000080fa00000006000200fa00000f78008f +:103e30001e0078009e007800110098001e00780097 +:103e4000900090001e007800010878000080fa00c1 +:103e5000000006000400fa00000f78001e00780041 +:103e6000100090009e0f500007003a001e007800de +:103e7000100078009e0f500003003a001000200050 +:103e800010079800020037000000eb0010079800b0 +:103e90001e0090000080fa00000006000400fa00f6 +:103ea000000f7800110798001e0078009000900025 +:103eb0001e009000110098001e0090001e0878005f +:103ec0001e009000100090009e00900001087800f5 +:103ed0001e0078009e009000110098000080fa00fb +:103ee000000006000400fa00000f78001107980097 +:103ef0001e0090009e007800110098001e007800bf +:103f0000900078001e009000010878001e009000cc +:103f1000100078009e009000110098001e007800ac +:103f20009e009000010878000080fa000000060062 +:103f30000400fa00100798000000eb00000f780062 +:103f40001e0090000000e000100032001e009000f3 +:103f5000900090001e009000808f50000b003200f7 +:103f60001e00900090009000010f78001e00780065 +:103f7000100090009e009000010878001e0078005c +:103f8000900090001e009000110098001e00780024 +:103f90000080fa00000006000600fa0010079800f2 +:103fa0001e009000900078001e009000808f50004e +:103fb00003003a000000eb00200798000c003700d7 +:103fc0001e009000100f78001e007800100078008e +:103fd0009e009000110098001e007800900078006c +:103fe0001e009000010878001e007800200798004d +:103ff0002e0090000080fa00000006000200fa0087 +:10400000000f78001e007800900078001e007800f5 +:1040100010009000900098001e0078009000900022 +:104020001e00780010007800800878000080fa00f8 +:10403000000006000800fa002007980031079800e9 +:104040000000eb00100798002e00900090009000f8 +:10405000010f7800090037002e0090009e0f10001d +:1040600003003a00100020001007980006003700f7 +:104070001e00780090009000010f78002e00900044 +:104080009e0f1000f4ff3a001e0090000080fa001e +:044090000000060026 +:020000040000fa +:10409400480c0000d20000000200000000000000f4 +:1040a400000000000000000000000000000000000c +:1040b40000000000000000000000000000000000fc +:1040c40000000000000000000000000000000000ec +:1040d40000000000000000000000000000000000dc +:1040e40000000000000000000000000000000000cc +:1040f40000000000000000000000000000000000bc +:1041040000000000000000000000000000000000ab +:10411400000000000000000000000000000000009b +:10412400000000000000000000000000000000008b +:10413400000000000000000000000000000000007b +:10414400000000000000000000000000000000006b +:10415400000000000000000000000000000000005b +:10416400000000000000000000000000000000004b +:10417400000000000000000000000000000000003b +:10418400000000000000000000000000000000002b +:10419400000000000000000000000000000000001b +:1041a400000000000000000000000000000000000b +:1041b40000000000000800004804000000000000a7 +:1041c400d60d000006000000020000000000000000 +:1041d400000000001a0d000098000000000000001c +:1041e400b20d0000240000000000000000000000e8 +:020000040000fa +:1041f400c1d4200091007800a0d4200001087800e8 +:104204009107780026003700801f7800600820009e +:104214001040a0004f007800000006002000f800c5 +:104224004200f8008e1f78008c9fbe008a9fbe005b +:10423400889fbe00869fbe00849fbe00829fbe00f2 +:10424400809fbe003600f8003200f8004400f800f9 +:104254003400f8001202800042a0a800f0ff2f00f2 +:1042640000018800600820001040a100a0d42000b4 +:10427400c1d4200091007800100078000100e00013 +:10428400070032000008e100050032000f08780042 +:1042940091077800a0d42000010878001202880059 +:1042a4003400f9004400f9003200f9003600f90046 +:1042b4004f00be004f01be004f02be004f03be00c0 +:1042c4004f04be004f05be004f06be004f077800e6 +:1042d4004200f9002000f900004006004200f80006 +:1042e40010028000000eb300100288004f00780016 +:1042f40000000600100288000000060000002000f4 +:1043040042a0af001000200042c0af001000200007 +:0c43140042e0af00100020000000060096 +:00000001FF diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml new file mode 100644 index 0000000..e2efc73 --- /dev/null +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml @@ -0,0 +1,232 @@ + + + + + + + + + ../tn_pic24_example_basic.c + + + Makefile + + + + ../../../../src/arch/pic32 + ../../../../../src/arch/pic32 + .. + ../../../../../src/arch/pic24_dspic + + Makefile + + + + localhost + PIC24FJ256GB106 + + + ICD3PlatformTool + C30 + 3_30 + 2 + + + + + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.properties b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.properties new file mode 100644 index 0000000..e69de29 diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml new file mode 100644 index 0000000..7cfa814 --- /dev/null +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml @@ -0,0 +1,18 @@ + + com.microchip.mplab.nbide.embedded.makeproject + + + tn_pic24_example_basic + c9dd49e3-2016-4363-9a07-cbe7b4d66428 + 0 + c + + + + UTF-8 + + ../../../../../src/arch/pic24_dspic/tneokernel_pic24.X + + + + diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c new file mode 100644 index 0000000..54bbc8c --- /dev/null +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -0,0 +1,535 @@ +/** + * TNeoKernel PIC32 basic example + */ + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include "p24Fxxxx.h" +#include "tn.h" + + + + +/******************************************************************************* + * HARDWARE CONFIGURATION + ******************************************************************************/ + +// {{{ + + +/* + + Config word 3 Example: Protect code memory from start (protect 128 flash pages) and protect + configuration block of programm memoty + + __CSP_CONFIG_3(CODE_WRITE_PROT_MEM_START | + CODE_WRITE_CONF_MEM_EN | + (128) + ); + */ + +#define __CSP_CONFIG_3(x) __attribute__((section("__CONFIG3.sec,code"))) int __CSP_CONFIG_3 = ((x) | 0x1E00) + +/* Write protection location */ + +#define CODE_WRITE_PROT_MEM_START (0 << 15) /* Code write protect from start of programm memory */ +#define CODE_WRITE_PROT_MEM_END (1 << 15) /* Code write protect from end of programm memory */ + +/* Write Protect Configuration Page */ + +#define CODE_WRITE_CONF_MEM_EN (1 << 14) /* Code configuration memory block write protect enabled */ +#define CODE_WRITE_CONF_MEM_DIS (0 << 14) /* Code configuration memory block write protect disabled */ + +/* Write protect enable */ + +#define CODE_WRITE_BLOCK_EN (0 << 13) /* Code write protect enabled */ +#define CODE_WRITE_BLOCK_DIS (1 << 13) /* Code write protect disabled */ + + +#define __CSP_CONFIG_2(x) __attribute__((section("__CONFIG2.sec,code"))) int __CSP_CONFIG_2 = ((x) | 0x0004) + +/* Two Speed Start-up: */ + +#define TWO_SPEED_STARTUP_EN (1 << 15) /* Enabled */ +#define TWO_SPEED_STARTUP_DIS (0 << 15) /* Disabled */ + +/* USB 96 MHz PLL Prescaler Select bits */ + +#define USB_PLL_PRESCALE_1 (0 << 12) /* 1:1 */ +#define USB_PLL_PRESCALE_2 (1 << 12) /* 1:2 */ +#define USB_PLL_PRESCALE_3 (2 << 12) /* 1:3 */ +#define USB_PLL_PRESCALE_4 (3 << 12) /* 1:4 */ +#define USB_PLL_PRESCALE_5 (4 << 12) /* 1:5 */ +#define USB_PLL_PRESCALE_6 (5 << 12) /* 1:6 */ +#define USB_PLL_PRESCALE_10 (6 << 12) /* 1:10 */ +#define USB_PLL_PRESCALE_12 (7 << 12) /* 1:12 */ + +/* Oscillator Selection: */ + +#define OSC_STARTUP_FRC (0 << 8) /* Fast RC oscillator */ +#define OSC_STARTUP_FRC_PLL (1 << 8) /* Fast RC oscillator w/ divide and PLL */ +#define OSC_STARTUP_PRIMARY (2 << 8) /* Primary oscillator (XT, HS, EC) */ +#define OSC_STARTUP_PRIMARY_PLL (3 << 8) /* Primary oscillator (XT, HS, EC) w/ PLL */ +#define OSC_STARTUP_SECONDARY (4 << 8) /* Secondary oscillator */ +#define OSC_STARTUP_LPRC (5 << 8) /* Low power RC oscillator */ +#define OSC_STARTUP_FRC_PS (7 << 8) /* Fast RC oscillator with divide */ + +/* Clock switching and clock montor: */ + +#define CLK_SW_EN_CLK_MON_EN (0 << 6) /* Both enabled */ +#define CLK_SW_EN_CLK_MON_DIS (1 << 6) /* Only clock switching enabled */ +#define CLK_SW_DIS_CLK_MON_DIS (3 << 6) /* Both disabled */ + +/* OSCO/RC15 function: */ + +#define OSCO_PIN_CLKO (1 << 5) /* OSCO or Fosc/2 */ +#define OSCO_PIN_GPIO (0 << 5) /* RC15 */ + +/* RP Register Protection */ + +#define PPS_REG_PROTECT_DIS (0 << 4) /* Unlimited Writes To RP Registers */ +#define PPS_REG_PROTECT_EN (1 << 4) /* Write RP Registers Once */ + +/* USB regulator control */ + +#define USB_REG_EN (0 << 3) +#define USB_REG_DIS (1 << 3) + +/* Oscillator Selection: */ + +#define PRIMARY_OSC_EC (0 << 0) /* External clock */ +#define PRIMARY_OSC_XT (1 << 0) /* XT oscillator */ +#define PRIMARY_OSC_HS (2 << 0) /* HS oscillator */ +#define PRIMARY_OSC_DIS (3 << 0) /* Primary disabled */ + + + +#define __CSP_CONFIG_1(x) __attribute__((section("__CONFIG1.sec,code"))) int __CSP_CONFIG_1 = ((x) | 0x8420) + +/* JTAG: */ + +#define JTAG_EN (1 << 14) /* Enabled */ +#define JTAG_DIS (0 << 14) /* Disabled */ + +/* Code Protect: */ + +#define CODE_PROTECT_EN (0 << 13) /* Enabled */ +#define CODE_PROTECT_DIS (1 << 13) /* Disabled */ + +/* Write Protect: */ + +#define CODE_WRITE_EN (1 << 12) /* Enabled */ +#define CODE_WRITE_DIS (0 << 12) /* Disabled */ + +/* Background Debugger: */ + +#define BACKGROUND_DEBUG_EN (0 << 11) /* Enabled */ +#define BACKGROUND_DEBUG_DIS (1 << 11) /* Disabled */ + +/* Clip-on Emulation mode: */ + +#define EMULATION_EN (0 << 10) /* Enabled */ +#define EMULATION_DIS (1 << 10) /* Disabled */ + +/* ICD pins select: */ + +#define ICD_PIN_PGX3 (1 << 8) /* EMUC/EMUD share PGC3/PGD3 */ +#define ICD_PIN_PGX2 (2 << 8) /* EMUC/EMUD share PGC2/PGD2 */ +#define ICD_PIN_PGX1 (3 << 8) /* EMUC/EMUD share PGC1/PGD1 */ + +/* Watchdog Timer: */ + +#define WDT_EN (1 << 7) /* Enabled */ +#define WDT_DIS (0 << 7) /* Disabled */ + +/* Windowed WDT: */ + +#define WDT_WINDOW_EN (0 << 6) /* Enabled */ +#define WDT_WINDOW_DIS (1 << 6) /* Disabled */ + +/* Watchdog prescaler: */ + +#define WDT_PRESCALE_32 (0 << 4) /* 1:32 */ +#define WDT_PRESCALE_128 (1 << 4) /* 1:128 */ + + +/* Watchdog postscale: */ + +#define WDT_POSTSCALE_1 ( 0 << 0) /* 1:1 */ +#define WDT_POSTSCALE_2 ( 1 << 0) /* 1:2 */ +#define WDT_POSTSCALE_4 ( 2 << 0) /* 1:4 */ +#define WDT_POSTSCALE_8 ( 3 << 0) /* 1:8 */ +#define WDT_POSTSCALE_16 ( 4 << 0) /* 1:16 */ +#define WDT_POSTSCALE_32 ( 5 << 0) /* 1:32 */ +#define WDT_POSTSCALE_64 ( 6 << 0) /* 1:64 */ +#define WDT_POSTSCALE_128 ( 7 << 0) /* 1:128 */ +#define WDT_POSTSCALE_256 ( 8 << 0) /* 1:256 */ +#define WDT_POSTSCALE_512 ( 9 << 0) /* 1:512 */ +#define WDT_POSTSCALE_1024 (10 << 0) /* 1:1024 */ +#define WDT_POSTSCALE_2048 (11 << 0) /* 1:2048 */ +#define WDT_POSTSCALE_4096 (12 << 0) /* 1:4096 */ +#define WDT_POSTSCALE_8192 (13 << 0) /* 1:8192 */ +#define WDT_POSTSCALE_16384 (14 << 0) /* 1:16384 */ +#define WDT_POSTSCALE_32768 (15 << 0) /* 1:32768 */ + +// }}} + +//#pragma config CONFIG1H = 0x08; + +__CSP_CONFIG_1(JTAG_DIS | /* JTAG disabled */ +#if defined(__DEBUG) + CODE_PROTECT_DIS | /* Code Protect disabled */ +#else + CODE_PROTECT_EN | /* TODO:change Code Protect enabled */ +#endif + CODE_WRITE_EN | /* Code write enabled */ +#if defined(__DEBUG) + BACKGROUND_DEBUG_EN | /* Debug enabled */ + EMULATION_EN | /* Emulation enabled */ +#else + BACKGROUND_DEBUG_DIS | /* Debug enabled */ + EMULATION_DIS | /* Emulation enabled */ +#endif + ICD_PIN_PGX2 | /* PGC2/PGD2 pins used for debug */ +#if defined(__DEBUG) + WDT_DIS | /* WDT disabled */ +#else + WDT_DIS | /* WDT disabled */ +#endif + WDT_WINDOW_DIS | /* WDT mode is not-windowed */ +WDT_PRESCALE_32 | /* WDT prescale is 1:32 */ +WDT_POSTSCALE_1 /* WDT postscale is 1:1 */ +); + +__CSP_CONFIG_2(TWO_SPEED_STARTUP_DIS | /* Two-speed startup disabled */ + USB_PLL_PRESCALE_4 | + OSC_STARTUP_PRIMARY_PLL | /* Startup oscillator is Primary with PLL */ + CLK_SW_DIS_CLK_MON_DIS | /* Clock switch disabled, monitor disabled */ + OSCO_PIN_CLKO | /* OSCO pin is clockout */ + PPS_REG_PROTECT_DIS | /* PPS runtime change enabled */ + USB_REG_DIS | + PRIMARY_OSC_HS /* Primary oscillator mode is HS */ + ); + +__CSP_CONFIG_3(CODE_WRITE_PROT_MEM_START | /* Code write protect block from start */ + CODE_WRITE_CONF_MEM_DIS | /* Code config memory block not protected */ + CODE_WRITE_BLOCK_DIS /* Code block protect disabled */ + ); + + + + + +/******************************************************************************* + * MACROS + ******************************************************************************/ + +//-- instruction that causes debugger to halt +#define PIC24_SOFTWARE_BREAK() {__asm__ volatile(".pword 0xDA4000"); __asm__ volatile ("nop");} + +//-- system frequency +#define SYS_FREQ 32000000UL + +//-- kernel ticks (system timer) frequency +#define SYS_TMR_FREQ 1000 + +//-- system timer prescaler +//#define SYS_TMR_PRESCALER T5_PS_1_8 +#define SYS_TMR_PRESCALER_VALUE 64 + +//-- system timer period (auto-calculated) +#define SYS_TMR_PERIOD \ + (SYS_FREQ / SYS_TMR_PRESCALER_VALUE / SYS_TMR_FREQ) + + + + +//-- idle task stack size, in words +#define IDLE_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 16) + +//-- interrupt stack size, in words +#define INTERRUPT_STACK_SIZE (TN_MIN_STACK_SIZE + 64) + +//-- stack sizes of user tasks +#define TASK_A_STK_SIZE (TN_MIN_STACK_SIZE + 96) +#define TASK_B_STK_SIZE (TN_MIN_STACK_SIZE + 96) +#define TASK_C_STK_SIZE (TN_MIN_STACK_SIZE + 96) + +//-- user task priorities +#define TASK_A_PRIORITY 7 +#define TASK_B_PRIORITY 6 +#define TASK_C_PRIORITY 5 + + + +/******************************************************************************* + * DATA + ******************************************************************************/ + +//-- Allocate arrays for stacks: stack for idle task +// and for interrupts are the requirement of the kernel; +// others are application-dependent. +// +// We use convenience macro TN_STACK_ARR_DEF() for that. + +TN_STACK_ARR_DEF(idle_task_stack, IDLE_TASK_STACK_SIZE); +TN_STACK_ARR_DEF(interrupt_stack, INTERRUPT_STACK_SIZE); + +TN_STACK_ARR_DEF(task_a_stack, TASK_A_STK_SIZE); +TN_STACK_ARR_DEF(task_b_stack, TASK_B_STK_SIZE); +TN_STACK_ARR_DEF(task_c_stack, TASK_C_STK_SIZE); + + + +//-- task structures + +struct TN_Task task_a = {}; +struct TN_Task task_b = {}; +struct TN_Task task_c = {}; + + + +/******************************************************************************* + * ISRs + ******************************************************************************/ + +/** + * system timer ISR + */ +//tn_soft_isr(_TIMER_5_VECTOR) + +void __attribute__((__interrupt__, auto_psv)) _T1Interrupt(void) +{ + IFS0bits.T1IF = 0; + volatile int b; + b = 1; + b = 1; + tn_tick_int_processing(); +} + + + +/******************************************************************************* + * FUNCTIONS + ******************************************************************************/ + +void appl_init(void); + +void task_a_body(void *par) +{ + //-- this is a first created application task, so it needs to perform + // all the application initialization. + appl_init(); + + //-- and then, let's get to the primary job of the task + // (job for which task was created at all) + for(;;) + { + //mPORTEToggleBits(BIT_0); + tn_task_sleep(500); + } +} + +void task_b_body(void *par) +{ + for(;;) + { + //mPORTEToggleBits(BIT_1); + tn_task_sleep(1000); + } +} + +void task_c_body(void *par) +{ + for(;;) + { + //mPORTEToggleBits(BIT_2); + tn_task_sleep(1500); + } +} + +/** + * Hardware init: called from main() with interrupts disabled + */ +void hw_init(void) +{ + //SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); + + //turn off ADC function for all pins + //AD1PCFG = 0xffffffff; + + //-- enable timer5 interrupt + T1CONbits.TCS = 0; + T1CONbits.TGATE = 0; + T1CONbits.TSIDL = 1; + + T1CONbits.TCKPS = 2; // 1:64 + PR1 = (SYS_TMR_PERIOD - 1); + + IFS0bits.T1IF = 0; + IEC0bits.T1IE = 1; + IPC0bits.T1IP = 2; + T1CONbits.TON = 1; + + IEC1bits.INT1IE = 1; + IPC5bits.INT1IP = 1; +} + +/** + * Application init: called from the first created application task + */ +void appl_init(void) +{ + //-- configure LED port pins + //mPORTESetPinsDigitalOut(BIT_0 | BIT_1 | BIT_2); + //mPORTEClearBits(BIT_0 | BIT_1 | BIT_2); + + //-- initialize various on-board peripherals, such as + // flash memory, displays, etc. + // (in this sample project there's nothing to init) + + //-- initialize various program modules + // (in this sample project there's nothing to init) + + + //-- create all the rest application tasks +#if 1 + tn_task_create( + &task_b, + task_b_body, + TASK_B_PRIORITY, + task_b_stack, + TASK_B_STK_SIZE, + NULL, + (TN_TASK_CREATE_OPT_START) + ); + + tn_task_create( + &task_c, + task_c_body, + TASK_C_PRIORITY, + task_c_stack, + TASK_C_STK_SIZE, + NULL, + (TN_TASK_CREATE_OPT_START) + ); +#endif +} + +//-- idle callback that is called periodically from idle task +void idle_task_callback (void) +{ +} + +//-- create first application task(s) +void init_task_create(void) +{ + //-- task A performs complete application initialization, + // it's the first created application task +#if 1 + tn_task_create( + &task_a, //-- task structure + task_a_body, //-- task body function + TASK_A_PRIORITY, //-- task priority + task_a_stack, //-- task stack + TASK_A_STK_SIZE, //-- task stack size (in words) + NULL, //-- task function parameter + TN_TASK_CREATE_OPT_START //-- creation option + ); + +#endif +} + +int main(void) +{ +#ifndef PIC32_STARTER_KIT + /*The JTAG is on by default on POR. A PIC32 Starter Kit uses the JTAG, but + for other debug tool use, like ICD 3 and Real ICE, the JTAG should be off + to free up the JTAG I/O */ + //DDPCONbits.JTAGEN = 0; +#endif + +#if 1 + //-- unconditionally disable interrupts + tn_arch_int_dis(); +#endif + + //-- init hardware + hw_init(); + +#if 0 + for (;;){ + volatile int i; + i++; + if (i > 10){ + i = 0; + IFS1bits.INT1IF = 1; + } + } +#endif + +#if 1 + //-- call to tn_sys_start() never returns + tn_sys_start( + idle_task_stack, + IDLE_TASK_STACK_SIZE, + interrupt_stack, + INTERRUPT_STACK_SIZE, + init_task_create, + idle_task_callback + ); +#endif + + //-- unreachable + return 1; +} + + + + + +void __attribute((__interrupt__, auto_psv)) _AddressError (void) +{ + PIC24_SOFTWARE_BREAK(); + //for(;;); +} + +/** + * + */ +void __attribute((__interrupt__, auto_psv)) _StackError (void) +{ + PIC24_SOFTWARE_BREAK(); + // for(;;); +} + +/** + * + */ +void __attribute((__interrupt__, auto_psv)) _MathError (void) +{ + PIC24_SOFTWARE_BREAK(); + //for(;;); +} + +/** + * + */ +void __attribute((__interrupt__, auto_psv)) _OscillatorFail (void) +{ + PIC24_SOFTWARE_BREAK(); + //for(;;); +} + +/** + * + * + * + */ +void __attribute((__interrupt__, auto_psv)) _DefaultInterrupt (void) +{ + PIC24_SOFTWARE_BREAK(); + //for(;;); +} diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S new file mode 100644 index 0000000..cac9098 --- /dev/null +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -0,0 +1,209 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + + .text + + /* External references */ + + .extern tn_curr_run_task + .extern tn_next_task_to_run + .extern IFS1 + .extern __tn_sw_restore + + /* Public functions declared in this file */ + + .global __tn_arch_context_switch_now_nosave + .global __tn_arch_context_switch_pend + .global __tn_arch_inside_isr + .global _tn_arch_sr_save_int_dis + .global _tn_arch_sr_restore + .global __INT1Interrupt + +/*---------------------------------------------------------------------------- +* Interrupts should be disabled here +*----------------------------------------------------------------------------*/ + +__tn_arch_context_switch_now_nosave: + + /* get new task's sp */ + + mov #_tn_next_task_to_run, W1 ; W1 = &tn_next_task_to_run + mov [W1], W1 ; W1 = tn_next_task_to_run + mov #_tn_curr_run_task, W0 ; W0 = &tn_curr_run_task + + mov W1, [W0] ; tn_curr_run_task = tn_next_task_to_run + + mov [W1], W15 ; SP = *tn_next_task_to_run + + bra __tn_sw_restore + + +/*---------------------------------------------------------------------------- +* +*----------------------------------------------------------------------------*/ + +__tn_arch_context_switch_pend: + + push W0 + mov #_IFS1, W0 + ; TODO: atomically!!! + bset [W0], #4 ; IFS1bits.INT1IF = 1 + pop W0 + + return + + +/*---------------------------------------------------------------------------- +* +*----------------------------------------------------------------------------*/ + +__INT1Interrupt: + + ;; Save current context + + push _SPLIM + push _SR + push W14 + push.d W12 + push.d W10 + push.d W8 + push.d W6 + push.d W4 + push.d W2 + push.d W0 + push _RCOUNT + push _TBLPAG + push _CORCON + push _PSVPAG + + mov _SR, W2 ; save SR state and disable system interrupts + bset _SR, #5 + + + mov #0xFFFF, W0 ; Prevent stack error exeption if any non OS interrupt will be + mov W0, _SPLIM + + mov #_IFS1, W0 + ; TODO: atomically!!! + bclr [W0], #4 ; IFS1bits.INT1IF = 0 + + ; next task + + mov #_tn_curr_run_task, W0 ; move current task stack pointer to W0 + mov #_tn_next_task_to_run, W1 ; move next task stack pointer to W1 + mov [W1], W1 + mov [W0], W0 + cp0 W1 + bra Z, __tn_sw_restore ; restore old context, if there is no next task + cp W1, W0 + bra Z, __tn_sw_restore ; restore old context, if next task is current task + + mov W15, [W0] ; exchange stack pointer + mov [W1], W15 + + mov #_tn_curr_run_task, W0 + mov W1, [W0] + + mov W2, _SR ; restore SR state and enable system interrupts + +__tn_sw_restore: + + ; Restore context on stack pointer + + pop _PSVPAG + pop _CORCON + pop _TBLPAG + pop _RCOUNT + pop.d W0 + pop.d W2 + pop.d W4 + pop.d W6 + pop.d W8 + pop.d W10 + pop.d W12 + pop W14 + pop _SR + pop _SPLIM + + retfie + +/*---------------------------------------------------------------------------- +* +*----------------------------------------------------------------------------*/ + +_tn_arch_sr_save_int_dis: + + push _SR + mov _SR W0 + ior #0xE0, W0 + mov W0 _SR + pop W0 + + return + + +/*---------------------------------------------------------------------------- +* +*----------------------------------------------------------------------------*/ + +_tn_arch_sr_restore: + + //TODO: restore only IPL field + mov W0, _SR, + + return + +/*---------------------------------------------------------------------------- +* +*----------------------------------------------------------------------------*/ + +__tn_arch_inside_isr: + /* TODO: optimize */ + mov #0, W0 + + btsc _SR, #5 + mov #1, W0 + btsc _SR, #6 + mov #1, W0 + btsc _SR, #7 + mov #1, W0 + + return + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h new file mode 100644 index 0000000..c72cdf6 --- /dev/null +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -0,0 +1,421 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * + * \file + * + * PIC32 architecture-dependent routines + * + */ + +#ifndef _TN_ARCH_PIC32_H +#define _TN_ARCH_PIC32_H + +//-- this include is needed to get build-time configuration +// (TN_DEBUG is used) +#include "../../core/tn_common.h" + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#define _TN_PIC32_INTSAVE_DATA_INVALID 0xffff + +#if TN_DEBUG +# define _TN_PIC32_INTSAVE_CHECK() \ +{ \ + if (tn_save_status_reg == _TN_PIC32_INTSAVE_DATA_INVALID){ \ + _TN_FATAL_ERROR(""); \ + } \ +} +#else +# define _TN_PIC32_INTSAVE_CHECK() /* nothing */ +#endif + +/** + * FFS - find first set bit. Used in `_find_next_task_to_run()` function. + * Say, for `0xa8` it should return `3`. + * + * May be not defined: in this case, naive algorithm will be used. + */ +//#define _TN_FFS(x) (32 - __builtin_clz((x) & (0 - (x)))) + +/** + * Used by the kernel as a signal that something really bad happened. + * Indicates TNeoKernel bugs as well as illegal kernel usage + * (e.g. sleeping in the idle task callback) + * + * Typically, set to assembler instruction that causes debugger to halt. + */ +#define _TN_FATAL_ERROR(error_msg, ...) \ + {__asm__ volatile(".pword 0xDA4000"); __asm__ volatile ("nop");} + + + +/** + * \def TN_ARCH_STK_ATTR_BEFORE + * + * Compiler-specific attribute that should be placed **before** declaration of + * array used for stack. It is needed because there are often additional + * restrictions applied to alignment of stack, so, to meet them, stack arrays + * need to be declared with these macros. + * + * @see TN_ARCH_STK_ATTR_AFTER + */ + +/** + * \def TN_ARCH_STK_ATTR_AFTER + * + * Compiler-specific attribute that should be placed **after** declaration of + * array used for stack. It is needed because there are often additional + * restrictions applied to alignment of stack, so, to meet them, stack arrays + * need to be declared with these macros. + * + * @see TN_ARCH_STK_ATTR_BEFORE + */ + +#if defined (__C30__) +# define TN_ARCH_STK_ATTR_BEFORE +# define TN_ARCH_STK_ATTR_AFTER +#else +# error "Unknown compiler" +#endif + +/** + * Minimum task's stack size, in words, not in bytes; includes a space for + * context plus for parameters passed to task's body function. + */ +#define TN_MIN_STACK_SIZE 36//TODO + +/** + * Width of `int` type. + */ +#define TN_INT_WIDTH 16 + +/** + * Unsigned integer type whose size is equal to the size of CPU register. + * Typically it's plain `unsigned int`. + */ +typedef unsigned int TN_UWord; + + +/** + * Maximum number of priorities available, this value usually matches + * `#TN_INT_WIDTH`. + * + * @see TN_PRIORITIES_CNT + */ +#define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH + +/** + * Value for infinite waiting, usually matches `UINT_MAX` + */ +#define TN_WAIT_INFINITE 0xFFFF + +/** + * Value for initializing the task's stack + */ +#define TN_FILL_STACK_VAL 0xFEED + + + + +/** + * Declares variable that is used by macros `TN_INT_DIS_SAVE()` and + * `TN_INT_RESTORE()` for storing status register value. + * + * It is good idea to initially set it to some invalid value, + * and if TN_DEBUG is non-zero, check it in TN_INT_RESTORE(). + * Then, we can catch bugs if someone tries to restore interrupts status + * without saving it first. + * + * @see `TN_INT_DIS_SAVE()` + * @see `TN_INT_RESTORE()` + */ +#define TN_INTSAVE_DATA \ + int tn_save_status_reg = _TN_PIC32_INTSAVE_DATA_INVALID; + +/** + * The same as `#TN_INTSAVE_DATA` but for using in ISR together with + * `TN_INT_IDIS_SAVE()`, `TN_INT_IRESTORE()`. + * + * @see `TN_INT_IDIS_SAVE()` + * @see `TN_INT_IRESTORE()` + */ +#define TN_INTSAVE_DATA_INT TN_INTSAVE_DATA + +/** + * \def TN_INT_DIS_SAVE() + * + * Disable interrupts and return previous value of status register, + * atomically. Similar `tn_arch_sr_save_int_dis()`, but implemented + * as a macro, so it is potentially faster. + * + * Uses `#TN_INTSAVE_DATA` as a temporary storage. + * + * @see `#TN_INTSAVE_DATA` + * @see `tn_arch_sr_save_int_dis()` + */ + +/** + * \def TN_INT_RESTORE() + * + * Restore previously saved status register. + * Similar to `tn_arch_sr_restore()`, but implemented as a macro, + * so it is potentially faster. + * + * Uses `#TN_INTSAVE_DATA` as a temporary storage. + * + * @see `#TN_INTSAVE_DATA` + * @see `tn_arch_sr_save_int_dis()` + */ + +# define TN_INT_DIS_SAVE() tn_save_status_reg = tn_arch_sr_save_int_dis() +# define TN_INT_RESTORE() _TN_PIC32_INTSAVE_CHECK(); \ + tn_arch_sr_restore(tn_save_status_reg) + +/** + * The same as `TN_INT_DIS_SAVE()` but for using in ISR. + * + * Uses `#TN_INTSAVE_DATA_INT` as a temporary storage. + * + * @see `#TN_INTSAVE_DATA_INT` + */ +#define TN_INT_IDIS_SAVE() TN_INT_DIS_SAVE() + +/** + * The same as `TN_INT_RESTORE()` but for using in ISR. + * + * Uses `#TN_INTSAVE_DATA_INT` as a temporary storage. + * + * @see `#TN_INTSAVE_DATA_INT` + */ +#define TN_INT_IRESTORE() TN_INT_RESTORE() + +/** + * Returns nonzero if interrupts are disabled, zero otherwise. + */ +#define TN_IS_INT_DISABLED() (/*TODO*/1) + +/** + * Pend context switch from interrupt. + */ +#define _TN_CONTEXT_SWITCH_IPEND_IF_NEEDED() \ + _tn_context_switch_pend_if_needed() + +/** + * Converts size in bytes to size in `#TN_UWord`. + * For 32-bit platforms, we should shift it by 2 bit to the right; + * for 16-bit platforms, we should shift it by 1 bit to the right. + */ +#define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 1) + + + +#endif //-- DOXYGEN_SHOULD_SKIP_THIS + + + + + + + + + + +// --------------------------------------------------------------------------- + +/** + * Interrupt handler wrapper macro for software context saving. + * + * Usage looks like the following: + * + * tn_soft_isr(_TIMER_1_VECTOR) + * { + * INTClearFlag(INT_T1); + * + * //-- do something useful + * } + * + * Note that you should not use `__ISR(_TIMER_1_VECTOR)` macro for that. + * + * @param vec interrupt vector number, such as `_TIMER_1_VECTOR`, etc. + */ +#define tn_soft_isr(vec) \ +__attribute__((__noinline__)) void _func##vec(void); \ +void __attribute__((naked, nomips16)) \ + __attribute__((vector(vec))) \ + _isr##vec(void) \ +{ \ + asm volatile(".set push"); \ + asm volatile(".set mips32r2"); \ + asm volatile(".set nomips16"); \ + asm volatile(".set noreorder"); \ + asm volatile(".set noat"); \ + \ + asm volatile("rdpgpr $sp, $sp"); \ + \ + /* Increase interrupt nesting count */ \ + asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ + asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("addiu $k1, $k1, 1"); \ + asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("ori $k0, $zero, 1"); \ + asm volatile("bne $k1, $k0, 1f"); \ + \ + /* Swap stack pointers if nesting count is one */ \ + asm volatile("lui $k0, %hi(tn_user_sp)"); \ + asm volatile("sw $sp, %lo(tn_user_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_int_sp)"); \ + asm volatile("lw $sp, %lo(tn_int_sp)($k0)"); \ + \ + asm volatile("1:"); \ + /* Save context on stack */ \ + asm volatile("addiu $sp, $sp, -92"); \ + asm volatile("mfc0 $k1, $14"); /* c0_epc*/ \ + asm volatile("mfc0 $k0, $12, 2"); /* c0_srsctl*/ \ + asm volatile("sw $k1, 84($sp)"); \ + asm volatile("sw $k0, 80($sp)"); \ + asm volatile("mfc0 $k1, $12"); /* c0_status*/ \ + asm volatile("sw $k1, 88($sp)"); \ + \ + /* Enable nested interrupts */ \ + asm volatile("mfc0 $k0, $13"); /* c0_cause*/ \ + asm volatile("ins $k1, $zero, 1, 15"); \ + asm volatile("ext $k0, $k0, 10, 6"); \ + asm volatile("ins $k1, $k0, 10, 6"); \ + asm volatile("mtc0 $k1, $12"); /* c0_status*/ \ + \ + /* Save caller-save registers on stack */ \ + asm volatile("sw $ra, 76($sp)"); \ + asm volatile("sw $t9, 72($sp)"); \ + asm volatile("sw $t8, 68($sp)"); \ + asm volatile("sw $t7, 64($sp)"); \ + asm volatile("sw $t6, 60($sp)"); \ + asm volatile("sw $t5, 56($sp)"); \ + asm volatile("sw $t4, 52($sp)"); \ + asm volatile("sw $t3, 48($sp)"); \ + asm volatile("sw $t2, 44($sp)"); \ + asm volatile("sw $t1, 40($sp)"); \ + asm volatile("sw $t0, 36($sp)"); \ + asm volatile("sw $a3, 32($sp)"); \ + asm volatile("sw $a2, 28($sp)"); \ + asm volatile("sw $a1, 24($sp)"); \ + asm volatile("sw $a0, 20($sp)"); \ + asm volatile("sw $v1, 16($sp)"); \ + asm volatile("sw $v0, 12($sp)"); \ + asm volatile("sw $at, 8($sp)"); \ + asm volatile("mfhi $v0"); \ + asm volatile("mflo $v1"); \ + asm volatile("sw $v0, 4($sp)"); \ + \ + /* Call ISR */ \ + asm volatile("la $t0, _func"#vec); \ + asm volatile("jalr $t0"); \ + asm volatile("sw $v1, 0($sp)"); \ + \ + /* Restore registers */ \ + asm volatile("lw $v1, 0($sp)"); \ + asm volatile("lw $v0, 4($sp)"); \ + asm volatile("mtlo $v1"); \ + asm volatile("mthi $v0"); \ + asm volatile("lw $at, 8($sp)"); \ + asm volatile("lw $v0, 12($sp)"); \ + asm volatile("lw $v1, 16($sp)"); \ + asm volatile("lw $a0, 20($sp)"); \ + asm volatile("lw $a1, 24($sp)"); \ + asm volatile("lw $a2, 28($sp)"); \ + asm volatile("lw $a3, 32($sp)"); \ + asm volatile("lw $t0, 36($sp)"); \ + asm volatile("lw $t1, 40($sp)"); \ + asm volatile("lw $t2, 44($sp)"); \ + asm volatile("lw $t3, 48($sp)"); \ + asm volatile("lw $t4, 52($sp)"); \ + asm volatile("lw $t5, 56($sp)"); \ + asm volatile("lw $t6, 60($sp)"); \ + asm volatile("lw $t7, 64($sp)"); \ + asm volatile("lw $t8, 68($sp)"); \ + asm volatile("lw $t9, 72($sp)"); \ + asm volatile("lw $ra, 76($sp)"); \ + \ + asm volatile("di"); \ + asm volatile("ehb"); \ + \ + /* Restore context */ \ + asm volatile("lw $k0, 84($sp)"); \ + asm volatile("mtc0 $k0, $14"); /* c0_epc */ \ + asm volatile("lw $k0, 80($sp)"); \ + asm volatile("mtc0 $k0, $12, 2"); /* c0_srsctl */ \ + asm volatile("addiu $sp, $sp, 92"); \ + \ + /* Decrease interrupt nesting count */ \ + asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ + asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("addiu $k1, $k1, -1"); \ + asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("bne $k1, $zero, 1f"); \ + asm volatile("lw $k1, -4($sp)"); \ + \ + /* Swap stack pointers if nesting count is zero */ \ + asm volatile("lui $k0, %hi(tn_int_sp)"); \ + asm volatile("sw $sp, %lo(tn_int_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_user_sp)"); \ + asm volatile("lw $sp, %lo(tn_user_sp)($k0)"); \ + \ + asm volatile("1:"); \ + asm volatile("wrpgpr $sp, $sp"); \ + asm volatile("mtc0 $k1, $12"); /* c0_status */ \ + asm volatile("eret"); \ + \ + asm volatile(".set pop"); \ + \ +} __attribute((__noinline__)) void _func##vec(void) + + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // _TN_ARCH_PIC32_H + diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c new file mode 100644 index 0000000..caea34e --- /dev/null +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -0,0 +1,99 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#include "tn_tasks.h" + + +TN_UWord *_tn_arch_stack_top_get( + TN_UWord *stack_low_address, + int stack_size + ) +{ + return stack_low_address; +} + +TN_UWord *_tn_arch_stack_init( + TN_TaskBody *task_func, + TN_UWord *stack_top, + void *param + ) +{ + + *(stack_top++) = task_func; + *(stack_top++) = 0; + *(stack_top++) = 0xffff/*SPLIM: TODO*/; + *(stack_top++) = 0x0103; // SR + *(stack_top++) = 0x1414; // W14 + *(stack_top++) = 0x1212; // W12 + *(stack_top++) = 0x1313; // W13 + *(stack_top++) = 0x1010; // W10 + *(stack_top++) = 0x1111; // W11 + *(stack_top++) = 0x0808; // W08 + *(stack_top++) = 0x0909; // W09 + *(stack_top++) = 0x0606; // W06 + *(stack_top++) = 0x0707; // W07 + *(stack_top++) = 0x0404; // W04 + *(stack_top++) = 0x0505; // W05 + *(stack_top++) = 0x0202; // W02 + *(stack_top++) = 0x0303; // W03 + *(stack_top++) = (TN_UWord)param; // W00 - task func param + *(stack_top++) = 0x0101; // W01 + *(stack_top++) = 0; // RCOUNT + *(stack_top++) = 0; // TBLPAG + *(stack_top++) = 0; // CORCON + *(stack_top++) = 0; // PSVPAG + + return stack_top; +} + +void tn_arch_int_dis(void) +{ + //__builtin_disable_interrupts(); + //TODO + tn_arch_sr_save_int_dis(); +} + +void tn_arch_int_en(void) +{ + //__builtin_enable_interrupts(); + //TODO +} + + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/Makefile b/src/arch/pic24_dspic/tneokernel_pic24.X/Makefile new file mode 100644 index 0000000..fca8e2c --- /dev/null +++ b/src/arch/pic24_dspic/tneokernel_pic24.X/Makefile @@ -0,0 +1,113 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... +# WARNING: the IDE does not call this target since it takes a long time to +# simply run make. Instead, the IDE removes the configuration directories +# under build and dist directly without calling make. +# This target is left here so people can do a clean when running a clean +# outside the IDE. + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml new file mode 100644 index 0000000..252d7a1 --- /dev/null +++ b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml @@ -0,0 +1,201 @@ + + + + + + + + + + ../tn_arch_pic24.S + ../tn_arch_pic24_c.c + + + ../../../core/tn_mutex.c + ../../../core/tn_sem.c + ../../../core/tn_tasks.c + ../../../core/tn_dqueue.c + ../../../core/tn_sys.c + ../../../core/tn_list.c + ../../../core/tn_eventgrp.c + ../../../core/tn_fmem.c + ../../../core/tn_timer.c + ../../../core/tn_exch.c + ../../../core/tn_exch_link_queue.c + + + + Makefile + + + + ../../../core + ../.. + + Makefile + + + + localhost + PIC24FJ192GB110 + + + ICD3PlatformTool + C30 + 3_30 + 2 + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.properties b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.properties new file mode 100644 index 0000000..e69de29 diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.xml b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.xml new file mode 100644 index 0000000..f9b4e6a --- /dev/null +++ b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.xml @@ -0,0 +1,16 @@ + + com.microchip.mplab.nbide.embedded.makeproject + + + tneokernel_pic24 + 455b33f3-b0bc-43d7-a5c4-84b529221aec + 0 + c + + + + windows-1251 + + + + diff --git a/src/arch/tn_arch.h b/src/arch/tn_arch.h index 46d2bba..cfff53c 100644 --- a/src/arch/tn_arch.h +++ b/src/arch/tn_arch.h @@ -58,6 +58,8 @@ #if defined(__PIC32MX__) #include "pic32/tn_arch_pic32.h" +#elif defined(__C30__) +#include "pic24_dspic/tn_arch_pic24.h" #else #error "unknown platform" #endif diff --git a/stuff/vimwiki/index.wiki b/stuff/vimwiki/index.wiki index cb3e3da..c52a464 100644 --- a/stuff/vimwiki/index.wiki +++ b/stuff/vimwiki/index.wiki @@ -12,6 +12,16 @@ * [ ] probably move _tn_memcpy_uword() to something like `tn_util.c` +=== PIC24/dsPIC port === + + * [ ] SPLIM + * [ ] tn_arch_sr_restore: restore only IPL field + * [ ] tn_arch_inside_isr: optimize + * [ ] TN_IS_INT_DISABLED() : implement + * [ ] tn_arch_int_en: implement (or remove?) + * [ ] handle IFS1 atomically (__tn_arch_context_switch_pend, __INT1Interrupt) + * [ ] ISR macro (with separate stack for ISRs) + === exchange methods === * tn_exch_create From b843bfa673e601675eb88b4e1b6f9aaf0c56365f Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 12:47:37 +0300 Subject: [PATCH 16/96] added _tn_arch_is_int_disabled() function, implemented for pic24 --- .../tn_pic24_example_basic.X.production.hex | 1093 ----------------- .../basic/arch/pic24/tn_pic24_example_basic.c | 8 + src/arch/pic24_dspic/tn_arch_pic24.S | 20 +- src/arch/pic24_dspic/tn_arch_pic24.h | 2 +- src/arch/tn_arch.h | 5 + 5 files changed, 32 insertions(+), 1096 deletions(-) delete mode 100644 examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex b/examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex deleted file mode 100644 index 284f754..0000000 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.X/dist/default/production/tn_pic24_example_basic.X.production.hex +++ /dev/null @@ -1,1093 +0,0 @@ -:020000040000fa -:080000000002040000000000f2 -:020000040000fa -:10040000cfdd20000e7f24000e01880000000000d8 -:100410000c000700a00422000100200011000700ca -:10042000000020000000e000020032000000020096 -:10043000000000004c1d0200000000000040da0037 -:100440000000fe004440a900000020000000e00081 -:100450000300320000002000a00188004440a800f2 -:100460000000060091018800800078000000eb0089 -:1004700015003700e280400032a0b4009101ba00bc -:10048000e280400032a0b4009102ba00e280400055 -:1004900032a0b4000002eb00472bde00f507b200eb -:1004a000602ce10004003a000059eb008301e900f0 -:1004b000fdff3e00040037006128e100010032002a -:1004c0000082eb00040007001101ba000200e00006 -:1004d000e8ff3a00000006003159ba008301e90044 -:1004e0000c0032002159ba008301e90008003200f3 -:1004f0000400e00003003a00e280400032a0b400b3 -:10050000f5ff370011d9ba008301e900faff3a007c -:100510008100e800e180400032a0b4000000060045 -:10052000b21c040000000000be1c0400000000001b -:10053000a41c040000000000301d040000000000a6 -:10054000361d0400000000005a03040000000000f3 -:100550005407040000000000e40c04000000000048 -:100560001008040000000000be1804000000000095 -:020000040000fa -:020000040005f5 -:0457f400003e000073 -:020000040000fa -:020000040005f5 -:0457f800ee3300008c -:020000040000fa -:020000040005f5 -:0457fc00609e0000ab -:020000040000fa -:10000800be1d0000a81d0000661d00007c1d00002c -:10001800921d0000be1d0000be1d0000be1d000098 -:10002800be1d0000be1d0000be1d0000761c0000a5 -:10003800be1d0000be1d0000be1d0000be1d00004c -:10004800be1d0000be1d0000be1d0000be1d00003c -:10005800be1d0000be1d0000be1d0000be1d00002c -:10006800be1d0000be1d0000be1d0000be1d00001c -:1000780010210000be1d0000be1d0000be1d0000b6 -:10008800be1d0000be1d0000be1d0000be1d0000fc -:10009800be1d0000be1d0000be1d0000be1d0000ec -:1000a800be1d0000be1d0000be1d0000be1d0000dc -:1000b800be1d0000be1d0000be1d0000be1d0000cc -:1000c800be1d0000be1d0000be1d0000be1d0000bc -:1000d800be1d0000be1d0000be1d0000be1d0000ac -:1000e800be1d0000be1d0000be1d0000be1d00009c -:1000f800be1d0000be1d0000be1d0000be1d00008c -:10010800be1d0000be1d0000be1d0000be1d00007b -:10011800be1d0000be1d0000be1d0000be1d00006b -:10012800be1d0000be1d0000be1d0000be1d00005b -:10013800be1d0000be1d0000be1d0000be1d00004b -:10014800be1d0000be1d0000be1d0000be1d00003b -:10015800be1d0000be1d0000be1d0000be1d00002b -:10016800be1d0000be1d0000be1d0000be1d00001b -:10017800be1d0000be1d0000be1d0000be1d00000b -:10018800be1d0000be1d0000be1d0000be1d0000fb -:10019800be1d0000be1d0000be1d0000be1d0000eb -:1001a800be1d0000be1d0000be1d0000be1d0000db -:1001b800be1d0000be1d0000be1d0000be1d0000cb -:1001c800be1d0000be1d0000be1d0000be1d0000bb -:1001d800be1d0000be1d0000be1d0000be1d0000ab -:1001e800be1d0000be1d0000be1d0000be1d00009b -:0801f800be1d0000be1d000049 -:020000040000fa -:10020800be1d0000a81d0000661d00007c1d00002a -:10021800921d0000be1d0000be1d0000be1d000096 -:10022800be1d0000be1d0000be1d0000761c0000a3 -:10023800be1d0000be1d0000be1d0000be1d00004a -:10024800be1d0000be1d0000be1d0000be1d00003a -:10025800be1d0000be1d0000be1d0000be1d00002a -:10026800be1d0000be1d0000be1d0000be1d00001a -:1002780010210000be1d0000be1d0000be1d0000b4 -:10028800be1d0000be1d0000be1d0000be1d0000fa -:10029800be1d0000be1d0000be1d0000be1d0000ea -:1002a800be1d0000be1d0000be1d0000be1d0000da -:1002b800be1d0000be1d0000be1d0000be1d0000ca -:1002c800be1d0000be1d0000be1d0000be1d0000ba -:1002d800be1d0000be1d0000be1d0000be1d0000aa -:1002e800be1d0000be1d0000be1d0000be1d00009a -:1002f800be1d0000be1d0000be1d0000be1d00008a -:10030800be1d0000be1d0000be1d0000be1d000079 -:10031800be1d0000be1d0000be1d0000be1d000069 -:10032800be1d0000be1d0000be1d0000be1d000059 -:10033800be1d0000be1d0000be1d0000be1d000049 -:10034800be1d0000be1d0000be1d0000be1d000039 -:10035800be1d0000be1d0000be1d0000be1d000029 -:10036800be1d0000be1d0000be1d0000be1d000019 -:10037800be1d0000be1d0000be1d0000be1d000009 -:10038800be1d0000be1d0000be1d0000be1d0000f9 -:10039800be1d0000be1d0000be1d0000be1d0000e9 -:1003a800be1d0000be1d0000be1d0000be1d0000d9 -:1003b800be1d0000be1d0000be1d0000be1d0000c9 -:1003c800be1d0000be1d0000be1d0000be1d0000b9 -:1003d800be1d0000be1d0000be1d0000be1d0000a9 -:1003e800be1d0000be1d0000be1d0000be1d000099 -:0803f800be1d0000be1d000047 -:020000040000fa -:100570000800fa0010002000000f78000000eb00d7 -:10058000200798000000eb00100798000d003700ce -:10059000706a80001e0060000000e000030032006e -:1005a0001e00900020079800090037001e00780008 -:1005b00000004000000f78001e0090000000e800de -:1005c000100798001e009000e90f5000f0ff340063 -:1005d0002e0090004200dd008080e800a0d12000c5 -:1005e00000804000100078000000e00009003200a8 -:1005f0002e0090004200dd008080e800a0d12000a5 -:1006000000804000100078000080e900300798006a -:10061000020037000000eb00300798003e00900019 -:10062000606a88000080fa00000006000200fa00fc -:10063000000f78001e00780030189000e70f50007f -:1006400002003a001e007800a50807001e0078008e -:1006500030189000e70f5000040032001e007800b0 -:1006600030189000e60f500002003a001e0078009b -:10067000b80807000080fa00000006000200fa0037 -:10068000000f78001e007800201890000000e000a5 -:10069000020032000040da00000000001e00780076 -:1006a000740807001e007800860407000080fa0026 -:1006b000000006000600fa001007980021079800c5 -:1006c0002e009000000f78008080eb001e00780064 -:1006d000020007000080fa00000006000400fa0093 -:1006e000000f7800110798009e0090001e0078000f -:1006f0000e0407001e007800060007000000e0005e -:1007000002003a001e007800470307000080fa004c -:10071000000006000400fa00000f78001e007800b8 -:10072000201890004200de00610060001007980071 -:100730001e0090000000e0000200320010002000c7 -:10074000100798001e0090000080fa0000000600cc -:100750001a00fa0050079800610798007207980085 -:10076000030f9800140f9800250f9800360f98007b -:100770000080eb00400798007e009000e90f5000d9 -:1007800008003a003e0890000000d10061006000bf -:100790000000e00003003a00b0ff2f00400f980077 -:1007a000860037007e0090000000e0001400350055 -:1007b0007e009000e90f500011003c009e08900060 -:1007c00030022000808f50000d0034006e00900039 -:1007d0000000e0000a0032005e0090000000e0002f -:1007e000070032000e0890000000e0000400320014 -:1007f0005e009000820007000000e000030032006d -:10080000b1ff2f00410f98006c0037000000eb0093 -:1008100030079800890b0700200798002e009000f1 -:10082000e10f5000060032002e0090000000e000b2 -:1008300003003200d0ff2f00400f98005f00370008 -:100840002e009000e10f500002003a00a40e0700b5 -:10085000400798005e009000ee0090004110980064 -:100860005e009000ae089000511098009e08900025 -:100870000e089000cc0c0700800078005e0090000d -:10088000211098005e0090009e08900031109800a2 -:100890005e009000fe00900061109800de00900065 -:1008a0000000eb00a01898005e01900090f62c006c -:1008b000b17a24000019980011199800de00900008 -:1008c0000000eb00b0189800de0090000000eb0084 -:1008d000c0189800de0090000000eb00b0089800ff -:1008e0000000eb00100798000e089000000f780041 -:1008f000070037009e007800d0ee2f0080087800b7 -:100900001e8fe8001e0090000000e800100798000d -:100910009e0090001e089000808f5000f5ff35006b -:100920005e0090000080e8003f0d07005e00900030 -:10093000660040005e019000a13520009d0907007f -:100940005e009000270007005e0090001e00070078 -:100950005e009000db0307005e009000f80040009e -:1009600020d420005f0d0700306a80000000e800fe -:10097000306a88003e089000610060000004e000da -:10098000020032005e0090000f0407002e0090006d -:10099000e10f500007003a004e009000e10f4000c8 -:1009a00002003a000040da00000000004e00900013 -:1009b000510e0700be009000410f98004e089000b5 -:1009c0000080fa00000006000200fa00000f780024 -:1009d000010220001e804000130d07000080fa0075 -:1009e000000006000200fa00000f78009e00780068 -:1009f0007c8040000c0d07000080fa00000006001b -:100a00000400fa00000f78001e0078000019900022 -:100a1000901990000000eb001007980090f62c0051 -:100a2000b17a2400800f5100818f590002003a00f2 -:100a300010002000100798001e0090000080fa00af -:100a4000000006000600fa00200798002e00900023 -:100a500067000700100798001e0090000000e000eb -:100a600025003a00570007000000e00003003a00ac -:100a7000d0ff2f00100798001f0037000080eb0008 -:100a8000000f7800160e0700000f78002e0090006f -:100a900020ff07000000e00004003a002e00900054 -:100aa000390007000000e00003003200c0ff2f0003 -:100ab00010079800080037002e009000240007005f -:100ac0000000e000020032002e00900086020700c5 -:100ad0002e009000510307000080eb009e0f1000d5 -:100ae00002003a000040da00000000001e0078001a -:100af000010e0700030007001e0090000080fa00ae -:100b0000000006000000fa00050007000000e000f9 -:100b100001003200bd0d07000080fa000000060051 -:100b20000200fa00516a8000606a80000001eb0058 -:100b3000020f7800808f5000020032001000200069 -:100b4000000f78001e0078000080fa000000060008 -:100b50000400fa00000f78001e00780020189000b2 -:100b600061006000100798001e0090000000e00087 -:100b70000200320010002000100798001e009000b4 -:100b80000080fa00000006000400fa00000f780060 -:100b90001e007800201890004300de006100600015 -:100ba000100798001e0090000000e00002003200d4 -:100bb00010002000100798001e0090000080fa002e -:100bc000000006000200fa009c0a07008000eb000b -:100bd000010f7800e10f500002003a0010002000e1 -:100be000000f78001e0078000080fa000000060068 -:100bf0000400fa00100798000000eb00000f7800d6 -:100c00001e0090000000e00003003a00b0ff2f003b -:100c1000000f7800060037001e00900078ff0700e4 -:100c20000000e00002003a0090ff2f00000f780063 -:100c30001e0078000080fa00000006000600fa009e -:100c4000200798002e009000e9ff07001007980089 -:100c50001e0090000000e00021003a00d9ff0700cc -:100c60000000e00003003a00d0ff2f0010079800ba -:100c70001b0037000080eb00000f7800980d070084 -:100c8000000f78002e009000a2fe07000000e00098 -:100c900003003a00c0ff2f0010079800080037003b -:100ca0002e009000ef0207002e0090000f000700ba -:100cb0000000e00002003a002e009000da01070078 -:100cc0000080eb009e0f100002003a000040da00a6 -:100cd000000000001e007800870d070089ff070054 -:100ce0001e0090000080fa00000006000400fa00d8 -:100cf000000f78001e007800201890000000d1003e -:100d000061006000100798001e0090000000e000e5 -:100d10000200320010002000100798001e00900012 -:100d20000080fa00000006000800fa002007980082 -:100d3000310798002e009000be009000e00f500098 -:100d4000e08f580003003a000080eb001007980085 -:100d50001a0037009bff07000000e00003003a0084 -:100d6000d0ff2f0010079800140037000080eb0020 -:100d7000000f78005a0d0700000f78002e01900038 -:100d8000be019000110020000000eb000e000700e3 -:100d90000080eb009e0f100002003a000040da00d5 -:100da000000000001e007800530d070055ff0700eb -:100db000506a8000c0189000110798001e00900033 -:100dc0000080fa00000006000800fa00000f78001a -:100dd000110798002207980033079800506a800096 -:100de000c1010700506a80002e029000be029000f0 -:100df0001e0190009e007800110207000080fa009a -:100e0000000006000200fa00000f78004175200083 -:100e10001e007800020007000080fa0000000600b3 -:100e20000800fa0020079800310798002e00900073 -:100e30006fff0700100798001e0090000000e00000 -:100e400016003a005fff07000000e00003003a00d0 -:100e5000d0ff2f0010079800100037000080eb0033 -:100e6000000f78001e0d0700000f7800be009000f4 -:100e70002e00900001000100100798000080eb0098 -:100e80009e0f100002003a000040da00000000004f -:100e90001e007800180d07001aff07001e009000c2 -:100ea0000080fa00000006000400fa001007980015 -:100eb0000000eb00000f78001e0090008bff070081 -:100ec0000000e000080032001e0090003018900082 -:100ed000e10f500004003a008000eb001e0090007b -:100ee000fefd070002003700c0ff2f00000f780052 -:100ef0001e0078000080fa00000006000200fa00e0 -:100f0000000f7800417520001e00780002000700e5 -:100f10000080fa00000006000800fa002007980090 -:100f2000310798002e00900031ff0700100798004d -:100f30001e0090000000e00016003a0018000700b4 -:100f40000000e00003003a00d0ff2f0010079800d7 -:100f5000100037000080eb00000f7800e00c070065 -:100f6000000f7800be0090002e00900001000100ec -:100f7000100798000080eb009e0f100002003a005e -:100f80000040da00000000001e007800da0c0700c4 -:100f9000dcfe07001e0090000080fa000000060042 -:100fa0000200fa00a50907008000eb00010f78009d -:100fb000e20f500002003a0010002000000f7800fd -:100fc0001e0078000080fa00000006000200fa000f -:100fd000000f780041ce20001e00780090ff07002f -:100fe0000080fa00000006000200fa00000f7800fe -:100ff00041ce20001e007800c7ff07000080fa00e5 -:10100000000006000200fa00000f780001812000b5 -:101010001e00780082ff07000080fa000000060032 -:101020000400fa00100798000000eb00000f7800a1 -:101030001e0090002dff07000000e00004003200b9 -:1010400071ff2f001e009000a4fd07000200370072 -:10105000c0ff2f00000f78001e0078000080fa000b -:10106000000006000200fa00000f78000181200055 -:101070001e007800a8ff07000080fa0000000600ac -:101080000600fa0020079800cefe07000000e000ee -:10109000110032000080eb00000f7800900c070078 -:1010a000000f7800506a8000100798001e00900022 -:1010b0000d0107001e00900070fd07002e0090003b -:1010c000610060000004e000020032001e00900099 -:1010d00003000700470c07000080fa00000006002c -:1010e0000400fa00100798000000eb00000f7800e1 -:1010f0001e009000a4fe07000000e00003003a007c -:10110000c0ff2f00000f78000a0037001e0090007b -:1011100078004000b90b0700306a80000000e90049 -:10112000306a88001e0190006000b8000019980025 -:10113000111998001e0078000080fa0000000600d7 -:101140000600fa00200798002e009000a8fe070075 -:10115000100798001e0090000000e00036003a00e2 -:1011600098fe07000000e00003003a00d0ff2f00c7 -:1011700010079800300037000080eb00000f780067 -:10118000570c0700000f78002e0090007efe07002d -:101190000000e00003003200c0ff2f00100798009d -:1011a0001d003700516a80002e009000808f500093 -:1011b00003003a00d0ff2f001007980016003700f8 -:1011c0002e00900062fe07000000e00003003200e5 -:1011d0002e009000c4000700070037002e0090008a -:1011e000c2fe07000000e000030032008000eb00b8 -:1011f0002e0090004d0107002e00900045fd0700d5 -:101200000000e000020032002e009000950107006f -:101210002e00900019fd07000080eb009e0f1000cb -:1012200002003a000040da00000000001e007800d2 -:10123000310c070033fe07001e0090000080fa000a -:10124000000006000600fa00200798002e0090001b -:1012500067fe0700100798001e0090000000e000e5 -:1012600014003a0057fe07000000e00003003a00b7 -:10127000d0ff2f00100798000e0037000080eb0011 -:10128000000f7800160c0700000f78002e00900069 -:1012900093ff0700100798000080eb009e0f1000de -:1012a00002003a000040da00000000001e00780052 -:1012b000110c07001e0090000080fa0000000600dc -:1012c0000800fa0020079800310798002e009000cf -:1012d00047fe0700100798001e0090000000e00085 -:1012e00015003a0037fe07000000e00003003a0056 -:1012f000d0ff2f00100798000f0037000080eb0090 -:10130000000f7800f60b0700000f78002e00900009 -:10131000a01890003e009000010878000080eb00cb -:101320009e0f100002003a000040da0000000000aa -:101330001e007800f00b07001e0090000080fa00ed -:10134000000006000800fa00200798003107980006 -:101350002e00900026fe0700100798001e00900047 -:101360000000e0002d003a003e0090000000e00088 -:10137000030035003e009000e80f500003003400e9 -:10138000b0ff2f0010079800240037000dfe070063 -:101390000000e00003003a00d0ff2f001007980083 -:1013a0001e0037000080eb00000f7800cc0b070018 -:1013b000000f78003e0090000000e00003003a00bb -:1013c0002e009000e0109000310798000000eb0024 -:1013d000100798002e009000ebfd07000000e000d1 -:1013e00003003200c0ff2f001007980003003700f1 -:1013f000be0090002e009000a50107000080eb00c9 -:101400009e0f100002003a000040da0000000000c9 -:101410001e007800b80b0700bafd07001e00900000 -:101420000080fa00000006000400fa00100798008f -:101430001e009000201890000000e0000200320022 -:101440000040da00000000001e009000f010900044 -:10145000010f78001e009000201890008000780096 -:101460000100a0001e009000211898001e009000ae -:101470000080e8009e00780008000700606a800095 -:10148000701090009e0f5000020034001e0090006b -:10149000606a88000080fa00000006000400fa007c -:1014a000000f7800110798001e0090004200dd0038 -:1014b00080007800a0d12000008040009e007800cd -:1014c000880a0700110020001e0090000008dd00bf -:1014d00080007800706a800000807000706a880068 -:1014e0000080fa00000006000600fa0010079800cd -:1014f0001e00900020189000e10f50000200320002 -:101500000040da00000000009e00900080d520001e -:10151000808f500002003a000040da000000000016 -:101520001e009000f0109000010f78001e00900047 -:10153000a0189000e0ff2f00808060001e00900047 -:10154000211898001e0090000080e8009e0078009e -:10155000220007000000e0000200320004fc070047 -:1015600019003700616a80001e009000808f5000d3 -:1015700015003a001e0078004200dd008080e8007f -:10158000a0d1200000804000100078000000e000a2 -:10159000090032001e0078004200dd008080e80073 -:1015a000a0d1200000804000100078000080e900f9 -:1015b00020079800020037000000eb002007980089 -:1015c000ae009000616a88001e0090000080e80074 -:1015d000150a07000080fa00000006000600fa0065 -:1015e00010079800210798001e009000830a07004a -:1015f0002e0090004200dd0080007800a0d1200085 -:1016000000804000130a0700000f78001e00e00071 -:1016100008003200110020002e0090000008dd00bc -:101620000080ea0080007800706a8000008060001e -:10163000706a88001e0078000080fa000000060032 -:101640000a00fa00000f780011079800220798009e -:1016500034079800450798001e007800a0189000f5 -:10166000b0ff2f00008060000000e00003003200a7 -:101670000040da00000000000f0037003e0090003c -:10168000ce009000e00f5000e08f580003003a00b9 -:101690000040da0000000000070037009e007800dc -:1016a00066804000710607000000e0000200320082 -:1016b0000040da00000000001e00780020189000b2 -:1016c000800078000110a0001e007800211898000a -:1016d0001e007800ae009000311898009e0078003f -:1016e000212090000010a000a02098001e00900073 -:1016f0000000e000060032009e80e8001e0090001e -:10170000f80907001e0078009e009000310898003c -:101710009e007800668040003e019000ce0190005f -:10172000cc0507000080fa00000006000800fa005f -:10173000000f7800110798001e007800a018900094 -:1017400090ff2f00008060000000e00006003a00db -:101750001e007800201890000000d1006100600099 -:101760000000e00002003a000040da000000000043 -:101770001e80e800b7090700300798001e007800b7 -:10178000300890008000eb00210798000000e00086 -:1017900002003a001000200020079800be009000d0 -:1017a0002e009000808f5000020032000040da00ce -:1017b000000000001e80e800100a07001e80e800fc -:1017c000990907001e00780098fb07009e0078002a -:1017d0000000eb00b00898001e0078009e0090000a -:1017e000411898009e00780066804000de050700e2 -:1017f0001e007800a0189000d0ff2f0080806000ad -:101800001e007800211898009e0078000000eb0070 -:10181000b01898000080fa00000006000200fa00ec -:10182000000f78001e007800a0189000d0ff2f0055 -:10183000008060000000e000020032000040da009a -:10184000000000001e007800201890008000780042 -:101850000120a0001e007800211898000080fa00e6 -:10186000000006000200fa00000f78001e00780059 -:10187000a018900090ff2f00008060000000e000a2 -:1018800006003a001e007800201890004200de009a -:10189000610060000000e00002003a000040da0051 -:1018a000000000001e007800a0189000b0ff2f007c -:1018b000808060001e007800211898000080fa00e7 -:1018c000000006000200fa00000f78001e007800f9 -:1018d000201890000000e000030032000040da0011 -:1018e000000000000f0037009e0078007c80400060 -:1018f000580907000000e00003003a000040da0049 -:101900000000000007003700010220001e80400098 -:10191000500907000000e00002003a000040da0031 -:10192000000000001e007800e01090001e0078000b -:10193000711098001e007800201890008000780038 -:101940000130a0001e007800211898009e00780049 -:101950000000eb00d01898000080fa00000006009c -:101960000200fa00000f78001e0078002018900096 -:10197000e80f5000020032000040da0000000000d2 -:101980001e007800501190001e007800a0109000fa -:101990001e00780040109000890807008000780041 -:1019a0001e007800010878001e007800a018900042 -:1019b00070ff2f00808060001e00780021189800c2 -:1019c0000080fa00000006000400fa0010079800ea -:1019d0000000eb00000f78001e0090006afc07007a -:1019e0000000e000050032001e009000dcff070050 -:1019f0001e0090008cfe070002003700c0ff2f0081 -:101a0000000f78001e0078000080fa000000060039 -:101a10000e00fa002007980031079800420798004e -:101a200053079800640798000000eb001007980027 -:101a30002e009000070907000000e00011003a00a6 -:101a40002e009000100090000080e900000f780048 -:101a50004e0090000000e00005003200ce01900032 -:101a60006e019000de0090001e007800030001006f -:101a7000be0090001e00780018fb07001000200038 -:101a8000100798001e0090000080fa000000060079 -:101a90000400fa00000f7800110798001e0078007b -:101aa0002bfc07000000e000040032009e009000c4 -:101ab0001e00780006000700030037001e007800b3 -:101ac0009e009000711098000080fa00000006004f -:101ad0000400fa00000f7800110798001e0078003b -:101ae0001bfc07000000e00002003a000040da00a2 -:101af000000000001e007800f01090001e80e8003a -:101b0000b6fe07001e0078009e009000711098003d -:101b10001e80e8009e00900060fe070094fa070017 -:101b20000080fa00000006000800fa002007980074 -:101b3000310798000000eb00100798002e0090007d -:101b40007008900064005000000f78000a00370011 -:101b50003e0090009e0f100003003a00100020008d -:101b6000100798000a0037001e007800300090002f -:101b700064005000000f78009e00780064804000f0 -:101b8000ae009000fc804000810f5000f0ff3a0052 -:101b90001e0090000080fa00000006000600fa0017 -:101ba000200798002e009000e01090001107980088 -:101bb0002e0090007008900064005000000f780024 -:101bc000080037009e0090001e00780015000700f6 -:101bd000100798001e00780030009000640050004c -:101be000000f78009e00780064804000ae009000f6 -:101bf000fc804000810f5000f2ff3a002e00900060 -:101c0000f01090001e009000808f50000300320002 -:101c10009e0090002e0090009dff07000080fa00bb -:101c2000000006000800fa0010079800210798003d -:101c30002e009000000f78001e00900060009000c1 -:101c400030079800be009000e18f50000400320081 -:101c50003e009000e20f5000090032000d003700f6 -:101c60001e009000000890009e0f50000b003d00e9 -:101c70001e00900080089000010f780007003700d8 -:101c80009e0078001e00900007000700000f7800fb -:101c9000020037000040da00000000001e0078005b -:101ca0000080fa00000006000800fa0020079800f3 -:101cb000310798003e009000100798002e00900019 -:101cc000100090000080e900000f78000c00370041 -:101cd0001e007800f01090001e009000808f5000d1 -:101ce00003003d001e007800f010900011079800de -:101cf0001e007800200090000080e900000f7800ae -:101d00009e80e8002e009000808f5000f0ff3a0087 -:101d10001e0090000080fa00000006000800fa0093 -:101d200020079800310798002e009000f0009000e6 -:101d3000110798001e00900030189000e70f500027 -:101d4000060032001e00900030189000e60f500090 -:101d5000020032000040da00000000001e00900087 -:101d600030089000000f78001e0090000102200053 -:101d7000808040003e0090000002b000590807003b -:101d80001e007800e80040002e009000680040002f -:101d9000420807009e0078003e00900062ff0700a6 -:101da0000000e00003003a009e0078002107980040 -:101db000ddff37000080fa00000006000800fa008e -:101dc00020079800310798002e009000d000900066 -:101dd000110798001e00900090009000010f7800fd -:101de000090037001e009000840807001e009000c4 -:101df0000d0807001e007800100798001e009000d4 -:101e000090009000010f78002e009000e800400044 -:101e10001e009000808f5000f2ff3a003e009000bc -:101e200090109000110798001e0090009000900004 -:101e3000010f7800090037001e0090006f080700ae -:101e40001e009000f80707001e0078001007980099 -:101e50001e00900090009000010f78003e0090005e -:101e600001022000808040001e009000808f500002 -:101e7000f1ff3a000080fa00000006000800fa00b6 -:101e800020079800310798002e009000f000900085 -:101e9000110798003e009000200007000000e000bd -:101ea0001c0032001e00900030189000e70f500018 -:101eb000040032001e00900030189000e60f500021 -:101ec00014003a001e00900030089000000f7800c7 -:101ed0009e0078003e00900013ff07000000e00025 -:101ee000090032003e00900030089000be009000d3 -:101ef0008aff07003e019000ae0090001000200015 -:101f000041060700030037001e00780020079800f4 -:101f1000ddff37000080fa00000006000400fa0030 -:101f2000000f78001e007800201890000000d100fb -:101f300061006000100798001e0090000000e000a3 -:101f40000200320010002000100798001e009000d0 -:101f50000080fa00000006000400fa00000f78007c -:101f6000110798009e00780068804000b9070700bc -:101f70000000e0000e003a001e0090000002b000d9 -:101f8000b40707000000e000020032000040da0061 -:101f9000000000001e0190009e0078000000eb0091 -:101fa000190607009e0090001e00780083ff0700be -:101fb0000080fa00000006000400fa0010079800f4 -:101fc0009e0090000000eb00900898001e0090001a -:101fd00064004000090807001e0090007000900097 -:101fe000eefe07001e0090009a0707000000e000c8 -:101ff000040032009e0090000000eb00f00098000a -:10200000150037001e009000100090000080e900cd -:10201000000f78001e009000f0009000212090003a -:102020000000a000a02098008000eb001e007800b7 -:10203000290007001e00900070019000a22090006f -:10204000e0ff2f0000806000202198009e007800b3 -:102050001e009000020007000080fa000000060049 -:102060000600fa0010079800210798001e00900053 -:10207000ae009000710098001e00900010089000c3 -:102080008000e8001e009000110898001e009000db -:10209000e40040002e0090007c0040009107070003 -:1020a0002e009000f01090001e009000ddfe070052 -:1020b000000f78002e009000701090009e0f5000ce -:1020c000030032009e0078002e00900070fe070092 -:1020d0000080fa00000006000400fa00000f7800fb -:1020e000110798009e0090001e0078008ffd0700e9 -:1020f0001e007800060007000000e00002003a0021 -:102100001e007800c8fc07000080fa0000000600ee -:102110000400fa00000f78001e00780020189000dc -:102120004200de0061006000100798001e00900071 -:102130000000e000020032001000200010079800ac -:102140001e0090000080fa00000006000800fa005f -:102150001007980021079800320798003e01900070 -:10216000ae0090001e0090001f000700000f7800d6 -:102170001e00e00019003a001e0090002a07070028 -:102180001e00900064004000270707001e0090001a -:1021900068004000240707001e009000ae00900079 -:1021a000610098009e0090000000eb00f000980095 -:1021b0001e009000be009000010898009e00900054 -:1021c0000000eb00900898001e01900050e42900e8 -:1021d0002171210020099800310998001e00780023 -:1021e0000080fa00000006000800fa0010079800be -:1021f00021079800320798000000eb00000f7800dc -:102200001e0090000000e00003003a00b0ff2f0025 -:10221000000f78001b0037001e0090001c00070014 -:102220000000e00003003200b0ff2f00000f780034 -:10223000140037002e009000e10f5000060032001d -:102240002e009000e20f500003003200b0ff2f007c -:10225000000f78000b0037002e009000e10f5000b7 -:1022600008003a003e0090000000e0000300350046 -:102270003e009000e80f500002003400b0ff2f0035 -:10228000000f78001e0078000080fa0000000600b1 -:102290000400fa00000f78001e007800200990006a -:1022a000b00990000000eb001007980050e42900ee -:1022b00021712100800f5100818f590002003a00e6 -:1022c00010002000100798001e0090000080fa0007 -:1022d000000006000600fa00200798002e0090007b -:1022e00052000700100798001e0090000000e00058 -:1022f0002d003a00420007000000e00003003a0011 -:10230000d0ff2f0010079800270037000080eb0057 -:10231000000f7800f2070700000f78002e009000f1 -:10232000700090000000e000080032002e009000d5 -:10233000f0009000506a8000808f5000030032004f -:10234000a0ff2f00100798000f0037002e0090000c -:10235000d80407002e009000700090000000e000fc -:10236000050032002e00900013ff07002e009000a1 -:1023700064004000ac0607002e0190006000b80029 -:1023800020099800310998000080eb009e0f100092 -:1023900002003a000040da00000000001e00780051 -:1023a000d5070700030007001e0090000080fa0018 -:1023b000000006000000fa00050007000000e00031 -:1023c00001003200910707000080fa0000000600bb -:1023d0000200fa00516a8000606a80000001eb0090 -:1023e000020f7800808f50000200320010002000a1 -:1023f000000f78001e0078000080fa000000060040 -:102400000200fa008d0407008000eb00010f780045 -:10241000e10f500002003a0010002000000f780089 -:102420001e0078000080fa00000006000400fa0098 -:10243000100798000000eb00000f78001e009000cd -:102440000000e00003003a00b0ff2f00000f78000a -:10245000060037001e0090008dff07000000e0001e -:1024600002003a0090ff2f00000f78001e00780055 -:102470000080fa00000006000c00fa003007980007 -:1024800042079800530798003e009000e7ff0700be -:10249000200798000000eb00100798002e00900025 -:1024a0000000e00050003a00d5ff07000000e00007 -:1024b00003003a00d0ff2f00200798004a003700a1 -:1024c0000080eb00000f780085070700000f780000 -:1024d0003e009000f0009000506a8000808f500015 -:1024e00008003a003e009000100890008000e800cc -:1024f0003e009000110898000000eb0020079800b3 -:10250000230037003e00900060009000e10f500073 -:1025100009003a00506a8000e01090003e009000f0 -:1025200000089000808f500003003d00a0ff2f00a6 -:1025300020079800160037003e00900070009000c1 -:102540000000e00004003a00516a80003e00900064 -:10255000c3fe07000e0037004e009000de00900022 -:10256000e00f5000e08f580003003a000080eb00bd -:1025700020079800060037004e019000de01900011 -:102580003e0090001b00070010002000100798007c -:102590008fff07000000e00005003a001e009000d9 -:1025a0000000e000020032000040da0000000000fd -:1025b0000080eb009e0f100002003a000040da009d -:1025c000000000001e0078004b07070079ff07009d -:1025d0001e0090000000e00003003200506a8000fe -:1025e000c0189000210798002e0090000080fa008b -:1025f000000006000800fa00100798002207980063 -:10260000330798001e00900060009000e20f500019 -:102610000f003a00506a8000f01090001e009000f9 -:102620007000900070109000808f500005003d00f9 -:10263000506a8000f01090001e0090007000900022 -:102640001e00070070002000000f78000200370015 -:1026500060002000000f78001e0090002e01900006 -:10266000be0190009e00780005000700516a8000be -:102670001e00900001fe07000080fa000000060026 -:102680000800fa00000f7800110798002207980050 -:1026900033079800506a800093fb0700506a80005f -:1026a0002e029000be0290001e0190009e00780055 -:1026b000e3fb07000080fa00000006000400fa00b7 -:1026c000000f7800110798001e007800f0109000ad -:1026d0001e009000808f5000180034001e0078000b -:1026e000180007000000e000040032009e00900087 -:1026f0001e007800f6fc0700100037001e0078006e -:102700009e009000711098001e00780003fe0700e4 -:102710000000e000090032001e0078003018900030 -:10272000e70f500005003a001e00780030089000c6 -:10273000f0009000010f7800e3ff37000080fa00fe -:10274000000006000400fa00000f78001e00780068 -:102750002018900061006000100798001e00900093 -:102760000000e00002003200100020001007980076 -:102770001e0090000080fa00000006000200fa002f -:10278000000f78006011b8001e0078003aff0700c3 -:102790000080fa00000006000600fa0020079800fa -:1027a0002e00900021ff0700100798001e009000e7 -:1027b0000000e0002c003a0011ff07000000e000dc -:1027c00003003a00d0ff2f001007980026003700c2 -:1027d0000080eb00000f7800c1060700000f7800b2 -:1027e0002e009000f0009000506a8000808f500012 -:1027f00003003200a0ff2f001007980012003700de -:102800002e009000100890008000e9002e0090003b -:10281000110898002e009000100890000000e000c1 -:1028200009003c002e009000100890000000e0001d -:1028300003003d000040da00000000000200370005 -:102840002e009000dcfd07000080eb009e0f1000c2 -:1028500002003a000040da00000000001e0078008c -:10286000a5060700d3fe07001e0090000080fa00b6 -:10287000000006000600fa00200798002e009000d5 -:102880007008900064005000100798001e0090002f -:102890003000900064005000000f780008003700fe -:1028a0001e009000c4fd07001e007800100798006d -:1028b0001e0078003000900064005000000f780087 -:1028c0001e009000e40040002e0090007c004000bc -:1028d000808f5000f2ff3a000080fa0000000600ee -:1028e0000200fa00000f78001e00780030189000f7 -:1028f000e70f5000020032000040da000000000044 -:102900001e00780020209000610060000000e000c0 -:102910000e003a001e00780030089000f000900091 -:10292000010f78001e0078009cfc07001e00780054 -:102930007afd07000000e000040032001e0078006d -:1029400030189000e70f5000f2ff32000080fa00cc -:10295000000006000200fa00000f78001e00780058 -:10296000300890009e0078007bfd07000080fa0090 -:10297000000006000800fa001007980021079800e0 -:1029800032079800ae0090001e0090000b00070078 -:10299000000f78001e00e00005003a003e019000a4 -:1029a000ae0090001e00900082010700000f78002a -:1029b0001e0078000080fa00000006000600fa0001 -:1029c00010079800210798000000eb00000f780026 -:1029d0001e0090000000e00003003a00b0ff2f004e -:1029e000000f7800060037001e0090000700070067 -:1029f0000000e00002003200b0ff2f00000f78005e -:102a00001e0078000080fa00000006000400fa00b2 -:102a1000000f78001e00780060019000f001900027 -:102a20000000eb0010079800c0fb270031a9290027 -:102a3000800f5100818f590002003a0010002000e1 -:102a4000100798001e0090000080fa0000000600a9 -:102a50000600fa00200798002e00900011000700e1 -:102a6000000f78001e00e0000b003a001c06070073 -:102a7000100798002e0090003b010700000f78001f -:102a80002e0190006000b80060019800710198006c -:102a90001e009000180607001e0078000080fa0053 -:102aa000000006000400fa00100798000000eb0088 -:102ab000000f78001e0090000000e00003003a00c4 -:102ac000b0ff2f00000f7800060037001e009000b6 -:102ad000ceff07000000e00002003a0090ff2f0048 -:102ae000000f78001e0078000080fa000000060049 -:102af0000a00fa0020079800320798004307980060 -:102b00002e009000e7ff0700000f78001e00e00095 -:102b100009003a00f2050700100798003e019000f6 -:102b2000ce0190002e009000ca000700000f780030 -:102b30001e009000f00507001e0078000080fa00db -:102b4000000006000600fa00200798002e00900002 -:102b5000d4ff0700000f78001e00e00007003a00d5 -:102b6000df050700100798002e009000fe00070008 -:102b7000000f78001e009000df0507001e0078009f -:102b80000080fa00000006000a00fa002007980002 -:102b900031079800420798002e009000c1ff0700ff -:102ba000000f78001e00e00009003a00cc05070085 -:102bb000100798004e019000be0090002e0090007b -:102bc00015010700000f78001e009000ca050700dd -:102bd0001e0078000080fa00000006000800fa00dd -:102be00020079800310798002e009000adff0700e5 -:102bf000000f78001e00e00009003a00b805070049 -:102c0000100798002e00900018010700800078003f -:102c10003e009000010878001e009000b6050700f5 -:102c20001e0078000080fa00000006000800fa008c -:102c300020079800310798002e00900099ff0700a8 -:102c4000000f78001e00e00008003a00a40507000d -:102c5000100798002e009000110107003e0190001f -:102c60000089be001e009000a30507001e0078002a -:102c70000080fa00000006000200fa0020db2000bd -:102c8000690407000000eb00000f78000700370020 -:102c90001e0078004200dd008000780060db20002c -:102ca00000804000600407001e0fe8007000200054 -:102cb0009e0f1000f6ff34000080fa0000000600ae -:102cc0000a00fa00806a80006700600040079800f0 -:102cd0004e0090000000e00041003a00a06d80002e -:102ce000300798003e0090001000900020079800e8 -:102cf000370037003e00900040019000d001900066 -:102d0000f0ff2f0001002000800f5100818f59003b -:102d1000080032003e00900040019000d001900079 -:102d20007000200001002000800f5100818f5900a9 -:102d300002003e000040da00000000003e0090006b -:102d4000d00090004000900068005000e0805800e3 -:102d50003e01900040019800510198003e00900013 -:102d600040019000d0019000700020000100200080 -:102d7000800f5100818f590010003e003e009000ee -:102d80009e0407003e0190003e009000d00090009d -:102d90004000900080007800806a80000080400041 -:102da000670060004200dd008000780060db2000ea -:102db00000804000820078004a0407002e00900046 -:102dc000300798002e009000100090002007980017 -:102dd000be00900020db2000808f5000c5ff3a002d -:102de0004e0090004200dd008000780060db200093 -:102df000008f40000b0037001e007800100090008c -:102e0000100798001e009000570007001e00900059 -:102e1000200190001e009000b00090001e00900065 -:102e2000020001001e0078000a0407000000e00014 -:102e3000f1ff32001e007800060407000000e000e9 -:102e400002003a000040da00000000000080fa00b2 -:102e5000000006000a00fa002007980032079800d8 -:102e6000430798000000eb00100798003e01900017 -:102e7000ce019000f0ff2f0001002000800f5100d4 -:102e8000818f5900050032003e009000ce00900076 -:102e9000e00f5000e08f580003003a00b0ff2f0011 -:102ea000100798002d0037002e0090002e0007001c -:102eb000100798003e019000ce01900070002000a5 -:102ec00001002000800f5100818f590012003e0048 -:102ed000be009000806a800000804000670f6000a4 -:102ee0001e007800cf80de002e0190004001980087 -:102ef000510198002e0190001e0078004200dd0074 -:102f00008000780060db20000080400082007800b4 -:102f1000f403070011003700806a800001002000e0 -:102f2000670160006000b80003002000020070002c -:102f3000838070003e019000ce01900000004100af -:102f4000818049002e0190004001980051019800b5 -:102f5000ae00900020db2000e20307001e0090007e -:102f60000080fa00000006000400fa001007980034 -:102f70000000eb00000f78001e0090003b000700ef -:102f80000000e000080032001e0190006000b80060 -:102f900040019800510198001e009000170407009e -:102fa0001e009000a00307001e0078000080fa00b9 -:102fb000000006000800fa0010079800210798009a -:102fc000320798003e019000ae0090001e00900075 -:102fd00011000700000f78001e00e0000b003a000f -:102fe0001e009000900307001e0190006000b800d2 -:102ff00040019800510198001e019000c0fb27007d -:1030000031a9290060019800710198001e00780024 -:103010000080fa00000006000800fa00100798007f -:1030200021079800320798000000eb00000f78009d -:103030002e0090000000e00003003a00b0ff2f00d7 -:10304000000f7800060037001e009000ae009000d0 -:10305000210098001e009000be00900031009800f2 -:103060001e0078000080fa00000006000400fa004c -:10307000000f78001e007800760307008000eb0048 -:10308000110798000000e00002003a001000200044 -:10309000100798001e0090000080fa000000060053 -:1030a0000800fa00300798006000b8001007980088 -:1030b000210798003e009000ecff07000000e000b0 -:1030c0002a003200806a8000670f60003e00900096 -:1030d00040019000d00190001e007800cf80de00fb -:1030e000800f5100818f59000a0036003e00900089 -:1030f00040019000d00190001e007800cf80de00db -:1031000000005100818059001007980021079800a5 -:10311000160037003e00900040019000d001900062 -:103120001e007800cf80de00800f5100818f590093 -:103130000c0031003e00900040019000d001900052 -:103140001e007800cf80de00000051008180590011 -:1031500068004000e08048001007980021079800b0 -:10316000020037000040da00000000001e0090005e -:10317000ae0090000080fa00000006000200fa0095 -:10318000000f7800c06e800000000100fdff3700d6 -:103190001000fa00200798003107980042079800b5 -:1031a0005307980064079800750798000000eb002b -:1031b000100798000f0037001e0090004200dd004d -:1031c00080007800a0d12000008040001603070096 -:1031d0001e00900080004000e0d920008080400068 -:1031e0000000eb00800878001e0090000000e8005e -:1031f000100798001e009000e90f5000eeff340009 -:1032000020d42000080307000000eb00306a88008b -:103210000000eb00406a88000000eb00706a880044 -:103220000000eb00806a88000000eb00906a8800d4 -:103230000000eb00606a88000000eb00506a880024 -:103240007e009000c06e88000000eb001007980020 -:103250000a0037001e009000000040008000780047 -:103260004e00900080804000d0ee2f008008780053 -:103270001e0090000000e800100798009e009000db -:103280005e009000808f5000f2ff3900de00900059 -:103290004e00900044020700b06a880076fe0700e6 -:1032a000be0090002e00900018000700000f78006c -:1032b0001e00e000020032000040da0000000000c2 -:1032c00080d52000606a880080d52000bef9070004 -:1032d000000f78001e00e000020032000040da001b -:1032e0000000000080d52000506a88006e00900029 -:1032f00000000100406a80000000a000406a8800d1 -:10330000bc0307000080fa00000006000400fa0079 -:10331000000f7800110798001e0090002600200082 -:103320008002eb00000278009e01780092002000ed -:10333000e18b210080d5200005f507000080fa0010 -:10334000000006000400fa000000eb0010079800df -:10335000680007000000e00003003a00d0ff2f00e3 -:1033600010079800110037000080eb00000f780074 -:10337000db030700000f7800806a80000000e8008f -:10338000806a88001f0007004dfe07000080eb00e8 -:103390009e0f100002003a000040da00000000001a -:1033a0001e007800d4030700030007001e009000f1 -:1033b0000080fa00000006000000fa000500070087 -:1033c0000000e00001003200900307000080fa00d6 -:1033d000000006000200fa00516a8000606a800066 -:1033e0000001eb00020f7800808f500002003200d5 -:1033f00010002000000f78001e0078000080fa0006 -:10340000000006000600fa00506a8000701090006c -:10341000200798002e00900080004000e0d9200096 -:1034200000804000100078000000e0002f00320013 -:10343000516a8000511890000000e800d0189800f0 -:10344000506a800050189000000178002e00900013 -:1034500080004000e0d9200000804000100078008b -:10346000800f510021003600516a80000000eb00ff -:10347000d01898002e0090004200dd0080007800f7 -:10348000a0d1200000804000000f78001e007800ce -:10349000700207000000e00014003a001e007800ef -:1034a00010009000100090009e0f50000f0032009e -:1034b0002e0090004200dd0080007800a0d12000a6 -:1034c000008040009a020700100798001e0190003b -:1034d0002e0090004200dd0080007800a0d1200086 -:1034e00000804000820078007e0207000080fa0021 -:1034f000000006000200fa00500007008000eb0008 -:10350000010f7800e20f500002003a001000200086 -:10351000000f78001e0078000080fa00000006000e -:103520000800fa0020079800310798000000eb001f -:1035300010079800280007000000e00003003a0090 -:10354000d0ff2f0010079800200037002e009000b9 -:103550000000e000090035002e009000e80f500048 -:1035600006003c003e0090000000e0000300350033 -:103570003e009000e10f400003003a00b0ff2f0032 -:1035800010079800110037000080eb00000f780052 -:1035900053030700000f78002e0090003e019000ba -:1035a00080004000e0d92000008040000208780040 -:1035b0000080eb009e0f100002003a000040da008d -:1035c000000000001e0078004b0307001e00900062 -:1035d0000080fa00000006000200fa001700070051 -:1035e0008000eb00010f7800e10f500002003a006c -:1035f00010002000000f78001e0078000080fa0004 -:10360000000006000000fa00806a80000080fa00d6 -:10361000000006000000fa00406a80000080fa0006 -:10362000000006000200fa00000f78001e0078007b -:10363000d06e88000080fa00000006000400fa0046 -:10364000406a8000610060000004e0000b0032006e -:103650002b0307000000e0000300320020002000e0 -:103660001007980002003700100020001007980093 -:103670001e009000000f7800020037000000eb00f1 -:10368000000f78001e0078000080fa00000006009d -:103690000000fa00506a80000080fa000000060076 -:1036a0000000fa00506a8000401090000080fa008c -:1036b000000006000600fa00200798002e00900087 -:1036c000100090000080e900100798001e00900094 -:1036d000200090000080e900000f7800090037000a -:1036e00081ff2f001e009000130007001e007800cd -:1036f000100798001e007800200090000080e9006c -:10370000000f78001e0090008080e8002e009000de -:10371000808f5000f2ff3a002e009000cd0107008c -:103720000000e00002003a000040da000000000063 -:103730000080fa00000006000400fa00000f780084 -:10374000110798009e0090001e007800f7f7070010 -:103750001e007800060007000000e00002003a00aa -:103760001e00780030f707000080fa000000060015 -:103770000400fa00000f78001e0078002018900066 -:103780004200de0061006000100798001e009000fb -:103790000000e00002003200100020001007980036 -:1037a0001e0090000080fa00000006000400fa00ed -:1037b00010079800406a8000000f7800416a80007e -:1037c0001e00900000807000406a88001e00780093 -:1037d0000080fa00000006000400fa0010079800bc -:1037e000406a8000000f78001e0090008080ea0090 -:1037f000406a800000806000406a88001e007800f7 -:103800000080fa00000006000600fa00000f7800b1 -:1038100011079800220798001e00e00009003200fe -:10382000b06e80000000e00002003a00200020009e -:10383000deff0700b06e80000000e800b06e880078 -:1038400008003700b06e80000000e900b06e88000c -:10385000b06e80000000e00002003a00200020006e -:10386000ddff0700d06e80000000e00005003200a0 -:10387000d36e80002e0190009e0090001e00780004 -:10388000030001000080fa00000006000800fa00b2 -:103890001007980021079800320798000000eb00fd -:1038a000000f78000b0037002e0090009000780089 -:1038b0001e009000010878001e0090000080e800c3 -:1038c000100798002e0090000080e8002007980064 -:1038d0001e0fe8009e0078003e009000808f500090 -:1038e000f1ff39000080fa00000006003600f80001 -:1038f000809fbe00829fbe00849fbe00869fbe0048 -:103900003400f80000002000a00188000200fa0046 -:103910008460a90010002000000f78001000200033 -:10392000000f780087fe07000080fa003400f900dd -:103930004f03be004f02be004f01be004f00be004d -:103940003600f900004006000200fa00000f78007f -:1039500030000700401f200001002000f2f40700a3 -:10396000fcff37000200fa00000f7800803e2000c4 -:1039700001002000ecf40700fcff37000200fa0011 -:10398000000f7800c05d200001002000e6f4070071 -:10399000fcff37000000fa000421a90004c1a900bf -:1039a00005a1a8004110200091407800f0ccb300a0 -:1039b00000c0600001c2b3000140700004e1b70024 -:1039c000301f2000100888008460a9009460a800bf -:1039d000510a200091407800f0c8b30000c0600098 -:1039e00001c2b30001407000a5e0b70005e1a800e6 -:1039f0009680a800e10a20009140780080cfb300b3 -:103a000000c060000004a000aee0b7000080fa0033 -:103a1000000006000000fa00160020008002eb0003 -:103a20004408200083a320006200200021cb210055 -:103a3000e0c8200046f30700160020008002eb00db -:103a40004408200003b4200052002000e1cb2100f4 -:103a500040cd20003ef307000080fa000000060081 -:103a60000000fa000080fa00000006000000fa00e2 -:103a7000160020008002eb00440820000393200081 -:103a80007200200041ca210080c4200030f30700ea -:103a90000080fa00000006000000fa00db000700ca -:103aa000bcff070005d3210064d32100430620009a -:103ab000828620004103200000802000b4fd070022 -:103ac000100020000080fa00000006003400f8001a -:103ad000881f780008002000a80188004f047800a3 -:103ae0000000fa000040da00000000000080fa0048 -:103af0003400f900004006003400f800881f780008 -:103b000008002000a80188004f0478000000fa0097 -:103b10000040da00000000000080fa003400f900e4 -:103b2000004006003400f800881f780008002000dc -:103b3000a80188004f0478000000fa000040da0075 -:103b4000000000000080fa003400f9000040060088 -:103b50003400f800881f780008002000a8018800c1 -:103b60004f0478000000fa000040da000000000076 -:103b70000080fa003400f900004006003400f8002c -:103b8000881f780008002000a80188004f047800f2 -:103b90000000fa000040da00000000000080fa0097 -:103ba0003400f900004006000400fa00000f78001d -:103bb000110798001e0078000080fa00000006003f -:103bc0000600fa00000f78001107980022079800fd -:103bd0001e007800800078001e0090000108780028 -:103be0001e0090000080e800100798009e009000e2 -:103bf0000000eb00800878001e0090000080e800c4 -:103c0000100798009e0090000080eb00800878006c -:103c10001e0090000080e800100798009e009000b1 -:103c200030102000800878001e0090000080e8001e -:103c3000100798009e009000404121008008780005 -:103c40001e0090000080e800100798009e00900081 -:103c500020212100800878001e0090000080e800ec -:103c6000100798009e0090003031210080087800f5 -:103c70001e0090000080e800100798009e00900051 -:103c800000012100800878001e0090000080e800fc -:103c9000100798009e009000101121008008780005 -:103ca0001e0090000080e800100798009e00900021 -:103cb00080802000800878001e0090000080e800ce -:103cc000100798009e0090009090200080087800d7 -:103cd0001e0090000080e800100798009e009000f1 -:103ce00060602000800878001e0090000080e800de -:103cf000100798009e0090007070200080087800e7 -:103d00001e0090000080e800100798009e009000c0 -:103d100040402000800878001e0090000080e800ed -:103d2000100798009e0090005050200080087800f6 -:103d30001e0090000080e800100798009e00900090 -:103d400020202000800878001e0090000080e800fd -:103d5000100798009e009000303020008008780006 -:103d60001e0090000080e800100798002e009000d0 -:103d7000800078001e009000010878001e0090006e -:103d80000080e800100798009e00900010102000ae -:103d9000800878001e0090000080e800100798005e -:103da0009e0090000000eb00800878001e0090004c -:103db0000080e800100798009e0090000000eb00d3 -:103dc000800878001e0090000080e800100798002e -:103dd0009e0090000000eb00800878001e0090001c -:103de0000080e800100798009e0090000000eb00a3 -:103df000800878001e0090000080e80010079800fe -:103e00001e0090000080fa00000006000000fa008a -:103e1000330107000080fa00000006000000fa00ed -:103e20000080fa00000006000200fa00000f78008f -:103e30001e0078009e007800110098001e00780097 -:103e4000900090001e007800010878000080fa00c1 -:103e5000000006000400fa00000f78001e00780041 -:103e6000100090009e0f500007003a001e007800de -:103e7000100078009e0f500003003a001000200050 -:103e800010079800020037000000eb0010079800b0 -:103e90001e0090000080fa00000006000400fa00f6 -:103ea000000f7800110798001e0078009000900025 -:103eb0001e009000110098001e0090001e0878005f -:103ec0001e009000100090009e00900001087800f5 -:103ed0001e0078009e009000110098000080fa00fb -:103ee000000006000400fa00000f78001107980097 -:103ef0001e0090009e007800110098001e007800bf -:103f0000900078001e009000010878001e009000cc -:103f1000100078009e009000110098001e007800ac -:103f20009e009000010878000080fa000000060062 -:103f30000400fa00100798000000eb00000f780062 -:103f40001e0090000000e000100032001e009000f3 -:103f5000900090001e009000808f50000b003200f7 -:103f60001e00900090009000010f78001e00780065 -:103f7000100090009e009000010878001e0078005c -:103f8000900090001e009000110098001e00780024 -:103f90000080fa00000006000600fa0010079800f2 -:103fa0001e009000900078001e009000808f50004e -:103fb00003003a000000eb00200798000c003700d7 -:103fc0001e009000100f78001e007800100078008e -:103fd0009e009000110098001e007800900078006c -:103fe0001e009000010878001e007800200798004d -:103ff0002e0090000080fa00000006000200fa0087 -:10400000000f78001e007800900078001e007800f5 -:1040100010009000900098001e0078009000900022 -:104020001e00780010007800800878000080fa00f8 -:10403000000006000800fa002007980031079800e9 -:104040000000eb00100798002e00900090009000f8 -:10405000010f7800090037002e0090009e0f10001d -:1040600003003a00100020001007980006003700f7 -:104070001e00780090009000010f78002e00900044 -:104080009e0f1000f4ff3a001e0090000080fa001e -:044090000000060026 -:020000040000fa -:10409400480c0000d20000000200000000000000f4 -:1040a400000000000000000000000000000000000c -:1040b40000000000000000000000000000000000fc -:1040c40000000000000000000000000000000000ec -:1040d40000000000000000000000000000000000dc -:1040e40000000000000000000000000000000000cc -:1040f40000000000000000000000000000000000bc -:1041040000000000000000000000000000000000ab -:10411400000000000000000000000000000000009b -:10412400000000000000000000000000000000008b -:10413400000000000000000000000000000000007b -:10414400000000000000000000000000000000006b -:10415400000000000000000000000000000000005b -:10416400000000000000000000000000000000004b -:10417400000000000000000000000000000000003b -:10418400000000000000000000000000000000002b -:10419400000000000000000000000000000000001b -:1041a400000000000000000000000000000000000b -:1041b40000000000000800004804000000000000a7 -:1041c400d60d000006000000020000000000000000 -:1041d400000000001a0d000098000000000000001c -:1041e400b20d0000240000000000000000000000e8 -:020000040000fa -:1041f400c1d4200091007800a0d4200001087800e8 -:104204009107780026003700801f7800600820009e -:104214001040a0004f007800000006002000f800c5 -:104224004200f8008e1f78008c9fbe008a9fbe005b -:10423400889fbe00869fbe00849fbe00829fbe00f2 -:10424400809fbe003600f8003200f8004400f800f9 -:104254003400f8001202800042a0a800f0ff2f00f2 -:1042640000018800600820001040a100a0d42000b4 -:10427400c1d4200091007800100078000100e00013 -:10428400070032000008e100050032000f08780042 -:1042940091077800a0d42000010878001202880059 -:1042a4003400f9004400f9003200f9003600f90046 -:1042b4004f00be004f01be004f02be004f03be00c0 -:1042c4004f04be004f05be004f06be004f077800e6 -:1042d4004200f9002000f900004006004200f80006 -:1042e40010028000000eb300100288004f00780016 -:1042f40000000600100288000000060000002000f4 -:1043040042a0af001000200042c0af001000200007 -:0c43140042e0af00100020000000060096 -:00000001FF diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index 54bbc8c..89c361b 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -305,6 +305,7 @@ void __attribute__((__interrupt__, auto_psv)) _T1Interrupt(void) IFS0bits.T1IF = 0; volatile int b; b = 1; + b = _tn_arch_is_int_disabled(); b = 1; tn_tick_int_processing(); } @@ -328,6 +329,7 @@ void task_a_body(void *par) for(;;) { //mPORTEToggleBits(BIT_0); + LATE ^= (1 << 0); tn_task_sleep(500); } } @@ -337,6 +339,7 @@ void task_b_body(void *par) for(;;) { //mPORTEToggleBits(BIT_1); + LATE ^= (1 << 1); tn_task_sleep(1000); } } @@ -346,6 +349,7 @@ void task_c_body(void *par) for(;;) { //mPORTEToggleBits(BIT_2); + LATE ^= (1 << 2); tn_task_sleep(1500); } } @@ -386,6 +390,10 @@ void appl_init(void) //mPORTESetPinsDigitalOut(BIT_0 | BIT_1 | BIT_2); //mPORTEClearBits(BIT_0 | BIT_1 | BIT_2); + TRISEbits.TRISE0 = 0; + TRISEbits.TRISE1 = 0; + TRISEbits.TRISE2 = 0; + //-- initialize various on-board peripherals, such as // flash memory, displays, etc. // (in this sample project there's nothing to init) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index cac9098..1c235d6 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -48,6 +48,7 @@ .global __tn_arch_context_switch_now_nosave .global __tn_arch_context_switch_pend .global __tn_arch_inside_isr + .global __tn_arch_is_int_disabled .global _tn_arch_sr_save_int_dis .global _tn_arch_sr_restore .global __INT1Interrupt @@ -167,9 +168,9 @@ __tn_sw_restore: _tn_arch_sr_save_int_dis: push _SR - mov _SR W0 + mov _SR, W0 ior #0xE0, W0 - mov W0 _SR + mov W0, _SR pop W0 return @@ -203,6 +204,21 @@ __tn_arch_inside_isr: return +__tn_arch_is_int_disabled: + /* TODO: optimize */ + + mov #0xE0, W0 + and _SR, WREG + lsr W0, #5, W0 + cp W0, #0x7 + bra Z, 1f + mov #0, W0 + bra 2f +1: + mov #1, W0 +2: + return + /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index c72cdf6..38475e9 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -232,7 +232,7 @@ typedef unsigned int TN_UWord; /** * Returns nonzero if interrupts are disabled, zero otherwise. */ -#define TN_IS_INT_DISABLED() (/*TODO*/1) +#define TN_IS_INT_DISABLED() (_tn_arch_is_int_disabled()) /** * Pend context switch from interrupt. diff --git a/src/arch/tn_arch.h b/src/arch/tn_arch.h index cfff53c..51c8323 100644 --- a/src/arch/tn_arch.h +++ b/src/arch/tn_arch.h @@ -160,6 +160,11 @@ TN_UWord *_tn_arch_stack_init( */ int _tn_arch_inside_isr(void); +/** + * TODO + */ +int _tn_arch_is_int_disabled(void); + /** * Called whenever we need to switch context from one task to another. * From 8a1720725cf278b4d114012b9cbdc2a7ca8b5b7b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 13:32:08 +0300 Subject: [PATCH 17/96] tn_arch_sr_restore now alters only IPL field --- src/arch/pic24_dspic/tn_arch_pic24.S | 10 ++++++---- stuff/vimwiki/index.wiki | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 1c235d6..5add789 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -80,7 +80,6 @@ __tn_arch_context_switch_pend: push W0 mov #_IFS1, W0 - ; TODO: atomically!!! bset [W0], #4 ; IFS1bits.INT1IF = 1 pop W0 @@ -118,7 +117,6 @@ __INT1Interrupt: mov W0, _SPLIM mov #_IFS1, W0 - ; TODO: atomically!!! bclr [W0], #4 ; IFS1bits.INT1IF = 0 ; next task @@ -182,8 +180,12 @@ _tn_arch_sr_save_int_dis: _tn_arch_sr_restore: - //TODO: restore only IPL field - mov W0, _SR, + mov W0, W1 + and #0xE0, W1 + mov _SR, W0 + xor W0, W1, W0 + and #0xE0, W0 + xor _SR return diff --git a/stuff/vimwiki/index.wiki b/stuff/vimwiki/index.wiki index c52a464..eca5185 100644 --- a/stuff/vimwiki/index.wiki +++ b/stuff/vimwiki/index.wiki @@ -14,13 +14,13 @@ === PIC24/dsPIC port === + * [X] tn_arch_sr_restore: restore only IPL field + * [X] TN_IS_INT_DISABLED() : implement + * [X] handle IFS1 atomically (__tn_arch_context_switch_pend, __INT1Interrupt) * [ ] SPLIM - * [ ] tn_arch_sr_restore: restore only IPL field - * [ ] tn_arch_inside_isr: optimize - * [ ] TN_IS_INT_DISABLED() : implement * [ ] tn_arch_int_en: implement (or remove?) - * [ ] handle IFS1 atomically (__tn_arch_context_switch_pend, __INT1Interrupt) * [ ] ISR macro (with separate stack for ISRs) + * [ ] tn_arch_inside_isr: optimize === exchange methods === From dd7a14d60904897e19f0472f9eb1d210e993002d Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 13:41:56 +0300 Subject: [PATCH 18/96] pic24: switch from INT1 to INT0 --- examples/basic/arch/pic24/tn_pic24_example_basic.c | 4 ++-- src/arch/pic24_dspic/tn_arch_pic24.S | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index 89c361b..d458217 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -377,8 +377,8 @@ void hw_init(void) IPC0bits.T1IP = 2; T1CONbits.TON = 1; - IEC1bits.INT1IE = 1; - IPC5bits.INT1IP = 1; + IEC0bits.INT0IE = 1; + IPC0bits.INT0IP = 1; } /** diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 5add789..6c33790 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -40,7 +40,7 @@ .extern tn_curr_run_task .extern tn_next_task_to_run - .extern IFS1 + .extern IFS0 .extern __tn_sw_restore /* Public functions declared in this file */ @@ -51,7 +51,7 @@ .global __tn_arch_is_int_disabled .global _tn_arch_sr_save_int_dis .global _tn_arch_sr_restore - .global __INT1Interrupt + .global __INT0Interrupt /*---------------------------------------------------------------------------- * Interrupts should be disabled here @@ -79,8 +79,8 @@ __tn_arch_context_switch_now_nosave: __tn_arch_context_switch_pend: push W0 - mov #_IFS1, W0 - bset [W0], #4 ; IFS1bits.INT1IF = 1 + mov #_IFS0, W0 + bset [W0], #0 ; IFS0bits.INT0IF = 1 pop W0 return @@ -90,7 +90,7 @@ __tn_arch_context_switch_pend: * *----------------------------------------------------------------------------*/ -__INT1Interrupt: +__INT0Interrupt: ;; Save current context @@ -116,8 +116,8 @@ __INT1Interrupt: mov #0xFFFF, W0 ; Prevent stack error exeption if any non OS interrupt will be mov W0, _SPLIM - mov #_IFS1, W0 - bclr [W0], #4 ; IFS1bits.INT1IF = 0 + mov #_IFS0, W0 + bclr [W0], #0 ; IFS0bits.INT0IF = 0 ; next task From 994cbd07c3954e4c8d2d1267b6776ef5e0c0d910 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 14:25:46 +0300 Subject: [PATCH 19/96] pic24: used registers are preserved in the tn_arch_sr_restore --- src/arch/pic24_dspic/tn_arch_pic24.S | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 6c33790..9145d3d 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -79,8 +79,10 @@ __tn_arch_context_switch_now_nosave: __tn_arch_context_switch_pend: push W0 + mov #_IFS0, W0 bset [W0], #0 ; IFS0bits.INT0IF = 1 + pop W0 return @@ -180,6 +182,9 @@ _tn_arch_sr_save_int_dis: _tn_arch_sr_restore: + push W0 + push W1 + mov W0, W1 and #0xE0, W1 mov _SR, W0 @@ -187,6 +192,9 @@ _tn_arch_sr_restore: and #0xE0, W0 xor _SR + pop W1 + pop W0 + return /*---------------------------------------------------------------------------- From 6a16a016f9ca44fc9a7589461d5e1605c206a7e7 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 14:52:05 +0300 Subject: [PATCH 20/96] _tn_arch_stack_init() now takes stack_size argument. PIC24: SPLIM is used. --- examples/basic/arch/pic24/tn_pic24_example_basic.c | 2 +- src/arch/pic24_dspic/tn_arch_pic24_c.c | 6 ++++-- src/arch/pic32/tn_arch_pic32.c | 1 + src/arch/tn_arch.h | 1 + src/core/tn_tasks.c | 1 + stuff/vimwiki/index.wiki | 3 ++- 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index d458217..7b79dab 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -247,7 +247,7 @@ __CSP_CONFIG_3(CODE_WRITE_PROT_MEM_START | /* Code write protect block from //-- idle task stack size, in words -#define IDLE_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 16) +#define IDLE_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 16 + 100/*TODO: remove*/) //-- interrupt stack size, in words #define INTERRUPT_STACK_SIZE (TN_MIN_STACK_SIZE + 64) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index caea34e..7cad48e 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -48,13 +48,15 @@ TN_UWord *_tn_arch_stack_top_get( TN_UWord *_tn_arch_stack_init( TN_TaskBody *task_func, TN_UWord *stack_top, + int stack_size, void *param ) { + TN_UWord *p_splim = stack_top + stack_size - 1 - 1; - *(stack_top++) = task_func; + *(stack_top++) = (TN_UWord)task_func; *(stack_top++) = 0; - *(stack_top++) = 0xffff/*SPLIM: TODO*/; + *(stack_top++) = (TN_UWord)p_splim; // SPLIM *(stack_top++) = 0x0103; // SR *(stack_top++) = 0x1414; // W14 *(stack_top++) = 0x1212; // W12 diff --git a/src/arch/pic32/tn_arch_pic32.c b/src/arch/pic32/tn_arch_pic32.c index d15c942..255a459 100644 --- a/src/arch/pic32/tn_arch_pic32.c +++ b/src/arch/pic32/tn_arch_pic32.c @@ -112,6 +112,7 @@ TN_UWord *_tn_arch_stack_top_get( TN_UWord *_tn_arch_stack_init( TN_TaskBody *task_func, TN_UWord *stack_top, + int stack_size, void *param ) { diff --git a/src/arch/tn_arch.h b/src/arch/tn_arch.h index 51c8323..d1e286e 100644 --- a/src/arch/tn_arch.h +++ b/src/arch/tn_arch.h @@ -152,6 +152,7 @@ TN_UWord *_tn_arch_stack_top_get( TN_UWord *_tn_arch_stack_init( TN_TaskBody *task_func, TN_UWord *stack_top, + int stack_size, void *param ); diff --git a/src/core/tn_tasks.c b/src/core/tn_tasks.c index 19772f8..71d33f7 100644 --- a/src/core/tn_tasks.c +++ b/src/core/tn_tasks.c @@ -1027,6 +1027,7 @@ void _tn_task_clear_dormant(struct TN_Task *task) task->stack_top = _tn_arch_stack_init( task->task_func_addr, task->base_stack_top, + task->stack_size, task->task_func_param ); diff --git a/stuff/vimwiki/index.wiki b/stuff/vimwiki/index.wiki index eca5185..319a26d 100644 --- a/stuff/vimwiki/index.wiki +++ b/stuff/vimwiki/index.wiki @@ -17,7 +17,8 @@ * [X] tn_arch_sr_restore: restore only IPL field * [X] TN_IS_INT_DISABLED() : implement * [X] handle IFS1 atomically (__tn_arch_context_switch_pend, __INT1Interrupt) - * [ ] SPLIM + * [X] SPLIM + * [ ] Rewrite context switch routine (__INT0Interrupt) * [ ] tn_arch_int_en: implement (or remove?) * [ ] ISR macro (with separate stack for ISRs) * [ ] tn_arch_inside_isr: optimize From 085788acd9d13519c421ef82b7a9a7a5b63d1bef Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 16:33:29 +0300 Subject: [PATCH 21/96] _ISR0Interrupt rewritten --- .../basic/arch/pic24/tn_pic24_example_basic.c | 6 +- src/arch/pic24_dspic/tn_arch_pic24.S | 70 ++++++++++++------- src/arch/pic24_dspic/tn_arch_pic24_c.c | 2 +- stuff/vimwiki/index.wiki | 3 +- 4 files changed, 50 insertions(+), 31 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index 7b79dab..05385b8 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -330,7 +330,7 @@ void task_a_body(void *par) { //mPORTEToggleBits(BIT_0); LATE ^= (1 << 0); - tn_task_sleep(500); + tn_task_sleep(50); } } @@ -340,7 +340,7 @@ void task_b_body(void *par) { //mPORTEToggleBits(BIT_1); LATE ^= (1 << 1); - tn_task_sleep(1000); + tn_task_sleep(100); } } @@ -350,7 +350,7 @@ void task_c_body(void *par) { //mPORTEToggleBits(BIT_2); LATE ^= (1 << 2); - tn_task_sleep(1500); + tn_task_sleep(150); } } diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 9145d3d..897d44c 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -41,7 +41,6 @@ .extern tn_curr_run_task .extern tn_next_task_to_run .extern IFS0 - .extern __tn_sw_restore /* Public functions declared in this file */ @@ -96,7 +95,6 @@ __INT0Interrupt: ;; Save current context - push _SPLIM push _SR push W14 push.d W12 @@ -110,40 +108,55 @@ __INT0Interrupt: push _TBLPAG push _CORCON push _PSVPAG + push _SPLIM - mov _SR, W2 ; save SR state and disable system interrupts - bset _SR, #5 + /* store sp in preemted task's TCB */ + mov #_tn_curr_run_task, W0 ; move current task stack pointer to W0 + mov [W0], W0 + mov W15, [W0] - mov #0xFFFF, W0 ; Prevent stack error exeption if any non OS interrupt will be - mov W0, _SPLIM + /* save SR in W2 */ + mov _SR, W2 - mov #_IFS0, W0 - bclr [W0], #0 ; IFS0bits.INT0IF = 0 + /* set SPLIM to max: effectively, turn stack pointer limit off */ - ; next task + mov #0xffff, W0 + mov W0, _SPLIM - mov #_tn_curr_run_task, W0 ; move current task stack pointer to W0 - mov #_tn_next_task_to_run, W1 ; move next task stack pointer to W1 - mov [W1], W1 - mov [W0], W0 - cp0 W1 - bra Z, __tn_sw_restore ; restore old context, if there is no next task - cp W1, W0 - bra Z, __tn_sw_restore ; restore old context, if next task is current task + /* disable interrupts */ + mov _SR, W0 + xor #0xE0, W0 + xor _SR - mov W15, [W0] ; exchange stack pointer - mov [W1], W15 + /* tn_curr_run_task = tn_next_task_to_run */ - mov #_tn_curr_run_task, W0 - mov W1, [W0] + mov #_tn_next_task_to_run, W1 ; W1 = &tn_next_task_to_run + mov [W1], W1 ; W1 = tn_next_task_to_run + mov #_tn_curr_run_task, W0 ; W0 = &tn_curr_run_task - mov W2, _SR ; restore SR state and enable system interrupts + mov W1, [W0] ; tn_curr_run_task = tn_next_task_to_run + + + /* Set new stack pointer (from newly activated task) */ + + mov [W1], W15 ; SP = *tn_next_task_to_run + + + /* clear INT0 pending bit */ + + mov #_IFS0, W0 + bclr [W0], #0 ; IFS0bits.INT0IF = 0 + + /* restore SR from W2 (and therefore enable interrupts) */ + + mov W2, _SR __tn_sw_restore: ; Restore context on stack pointer + pop _SPLIM pop _PSVPAG pop _CORCON pop _TBLPAG @@ -157,7 +170,6 @@ __tn_sw_restore: pop.d W12 pop W14 pop _SR - pop _SPLIM retfie @@ -168,9 +180,15 @@ __tn_sw_restore: _tn_arch_sr_save_int_dis: push _SR - mov _SR, W0 - ior #0xE0, W0 - mov W0, _SR + + ;mov _SR, W0 + ;ior #0xE0, W0 + ;mov W0, _SR + + mov _SR, W0 + xor #0xE0, W0 + xor _SR + pop W0 return diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 7cad48e..f183af9 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -56,7 +56,6 @@ TN_UWord *_tn_arch_stack_init( *(stack_top++) = (TN_UWord)task_func; *(stack_top++) = 0; - *(stack_top++) = (TN_UWord)p_splim; // SPLIM *(stack_top++) = 0x0103; // SR *(stack_top++) = 0x1414; // W14 *(stack_top++) = 0x1212; // W12 @@ -77,6 +76,7 @@ TN_UWord *_tn_arch_stack_init( *(stack_top++) = 0; // TBLPAG *(stack_top++) = 0; // CORCON *(stack_top++) = 0; // PSVPAG + *(stack_top++) = (TN_UWord)p_splim; // SPLIM return stack_top; } diff --git a/stuff/vimwiki/index.wiki b/stuff/vimwiki/index.wiki index 319a26d..77c925e 100644 --- a/stuff/vimwiki/index.wiki +++ b/stuff/vimwiki/index.wiki @@ -18,7 +18,8 @@ * [X] TN_IS_INT_DISABLED() : implement * [X] handle IFS1 atomically (__tn_arch_context_switch_pend, __INT1Interrupt) * [X] SPLIM - * [ ] Rewrite context switch routine (__INT0Interrupt) + * [X] Rewrite context switch routine (__INT0Interrupt) + * [ ] ffs * [ ] tn_arch_int_en: implement (or remove?) * [ ] ISR macro (with separate stack for ISRs) * [ ] tn_arch_inside_isr: optimize From f2cd053156423c7b6fa0cefa8884aedd6db3e356 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 19:27:33 +0300 Subject: [PATCH 22/96] in order to avoid conflicts with other headers (usually chip-dependent ones), the following refactoring performed: BOOL -> TN_BOOL TRUE -> TN_TRUE FALSE -> TN_FALSE NULL -> TN_NULL --- src/core/internal/_tn_dqueue.h | 2 +- src/core/internal/_tn_eventgrp.h | 8 ++--- src/core/internal/_tn_exch.h | 2 +- src/core/internal/_tn_exch_link.h | 2 +- src/core/internal/_tn_fmem.h | 2 +- src/core/internal/_tn_list.h | 8 ++--- src/core/internal/_tn_mutex.h | 2 +- src/core/internal/_tn_sem.h | 2 +- src/core/internal/_tn_sys.h | 6 ++-- src/core/internal/_tn_tasks.h | 24 +++++++------- src/core/internal/_tn_timer.h | 4 +-- src/core/tn_common.h | 20 ++++++------ src/core/tn_dqueue.c | 24 +++++++------- src/core/tn_dqueue.h | 6 ++-- src/core/tn_eventgrp.c | 22 ++++++------- src/core/tn_eventgrp.h | 4 +-- src/core/tn_exch.c | 8 ++--- src/core/tn_exch.h | 2 +- src/core/tn_exch_link.c | 8 ++--- src/core/tn_exch_link.h | 2 +- src/core/tn_exch_link_queue.c | 4 +-- src/core/tn_exch_link_queue.h | 2 +- src/core/tn_fmem.c | 20 ++++++------ src/core/tn_list.c | 14 ++++----- src/core/tn_mutex.c | 32 +++++++++---------- src/core/tn_sem.c | 12 +++---- src/core/tn_sys.c | 14 ++++----- src/core/tn_sys.h | 14 ++++----- src/core/tn_tasks.c | 52 +++++++++++++++---------------- src/core/tn_tasks.h | 2 +- src/core/tn_timer.c | 10 +++--- src/core/tn_timer.h | 8 ++--- 32 files changed, 171 insertions(+), 171 deletions(-) diff --git a/src/core/internal/_tn_dqueue.h b/src/core/internal/_tn_dqueue.h index 0017b10..9267445 100644 --- a/src/core/internal/_tn_dqueue.h +++ b/src/core/internal/_tn_dqueue.h @@ -79,7 +79,7 @@ extern "C" { /*}*/ * Checks whether given queue object is valid * (actually, just checks against `id_dque` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_dqueue_is_valid( +static inline TN_BOOL _tn_dqueue_is_valid( struct TN_DQueue *dqueue ) { diff --git a/src/core/internal/_tn_eventgrp.h b/src/core/internal/_tn_eventgrp.h index b786af8..3d96f18 100644 --- a/src/core/internal/_tn_eventgrp.h +++ b/src/core/internal/_tn_eventgrp.h @@ -115,13 +115,13 @@ enum TN_RCode _tn_eventgrp_link_reset( * for example, #TN_DQueue. * * @param set - * - if `TRUE`, flag(s) are being set; - * - if `FALSE`, flag(s) are being cleared. + * - if `TN_TRUE`, flag(s) are being set; + * - if `TN_FALSE`, flag(s) are being cleared. * */ enum TN_RCode _tn_eventgrp_link_manage( struct TN_EGrpLink *eventgrp_link, - BOOL set + TN_BOOL set ); @@ -134,7 +134,7 @@ enum TN_RCode _tn_eventgrp_link_manage( * Checks whether given event group object is valid * (actually, just checks against `id_event` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_eventgrp_is_valid( +static inline TN_BOOL _tn_eventgrp_is_valid( struct TN_EventGrp *eventgrp ) { diff --git a/src/core/internal/_tn_exch.h b/src/core/internal/_tn_exch.h index e63ffab..c5da843 100644 --- a/src/core/internal/_tn_exch.h +++ b/src/core/internal/_tn_exch.h @@ -97,7 +97,7 @@ enum TN_RCode _tn_exch_read( * Checks whether given exchange object is valid * (actually, just checks against `id_exch` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_exch_is_valid( +static inline TN_BOOL _tn_exch_is_valid( struct TN_Exch *exch ) { diff --git a/src/core/internal/_tn_exch_link.h b/src/core/internal/_tn_exch_link.h index bb9451a..062a793 100644 --- a/src/core/internal/_tn_exch_link.h +++ b/src/core/internal/_tn_exch_link.h @@ -102,7 +102,7 @@ enum TN_RCode _tn_exch_link_delete( * Checks whether given exchange link object is valid * (actually, just checks against `id_exch_link` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_exch_link_is_valid( +static inline TN_BOOL _tn_exch_link_is_valid( struct TN_ExchLink *exch_link ) { diff --git a/src/core/internal/_tn_fmem.h b/src/core/internal/_tn_fmem.h index 97542e8..00040cd 100644 --- a/src/core/internal/_tn_fmem.h +++ b/src/core/internal/_tn_fmem.h @@ -79,7 +79,7 @@ extern "C" { /*}*/ * Checks whether given fixed memory pool object is valid * (actually, just checks against `id_fmp` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_fmem_is_valid( +static inline TN_BOOL _tn_fmem_is_valid( struct TN_FMem *fmem ) { diff --git a/src/core/internal/_tn_list.h b/src/core/internal/_tn_list.h index 3122453..9b0bc23 100644 --- a/src/core/internal/_tn_list.h +++ b/src/core/internal/_tn_list.h @@ -124,10 +124,10 @@ extern "C" { /*}*/ * @type: the type of the struct this is embedded in. * @member: the name of the TN_ListItem member within the struct. * - * Note that if the list is empty, it returns NULL. + * Note that if the list is empty, it returns TN_NULL. */ #define _tn_list_first_entry_or_null(ptr, type, member) \ - (!_tn_list_empty(ptr) ? _tn_list_first_entry(ptr, type, member) : NULL) + (!_tn_list_empty(ptr) ? _tn_list_first_entry(ptr, type, member) : TN_NULL) /** * _tn_list_next_entry - get the next element in list @@ -356,7 +356,7 @@ void _tn_list_reset(struct TN_ListItem *list); /** * Checks whether the list is empty. */ -BOOL _tn_list_is_empty(struct TN_ListItem *list); +TN_BOOL _tn_list_is_empty(struct TN_ListItem *list); /** * Insert an entry at the beginning of the list. @@ -419,7 +419,7 @@ void _tn_list_remove_entry(struct TN_ListItem *entry); * @param entry * Item to check. */ -BOOL _tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry); +TN_BOOL _tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/core/internal/_tn_mutex.h b/src/core/internal/_tn_mutex.h index f0a4e19..2419313 100644 --- a/src/core/internal/_tn_mutex.h +++ b/src/core/internal/_tn_mutex.h @@ -110,7 +110,7 @@ static inline void _tn_mutex_on_task_wait_complete(struct TN_Task *task) {} * Checks whether given mutex object is valid * (actually, just checks against `id_mutex` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_mutex_is_valid( +static inline TN_BOOL _tn_mutex_is_valid( struct TN_Mutex *mutex ) { diff --git a/src/core/internal/_tn_sem.h b/src/core/internal/_tn_sem.h index 244502a..e1854c1 100644 --- a/src/core/internal/_tn_sem.h +++ b/src/core/internal/_tn_sem.h @@ -79,7 +79,7 @@ extern "C" { /*}*/ * Checks whether given semaphore object is valid * (actually, just checks against `id_sem` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_sem_is_valid( +static inline TN_BOOL _tn_sem_is_valid( struct TN_Sem *sem ) { diff --git a/src/core/internal/_tn_sys.h b/src/core/internal/_tn_sys.h index 6953a60..d814a0f 100644 --- a/src/core/internal/_tn_sys.h +++ b/src/core/internal/_tn_sys.h @@ -181,7 +181,7 @@ enum TN_StateFlag _tn_sys_state_flags_clear(enum TN_StateFlag flags); * by means of `task->deadlock_list`. * */ -void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task); +void _tn_cry_deadlock(TN_BOOL active, struct TN_Mutex *mutex, struct TN_Task *task); #endif /** @@ -213,9 +213,9 @@ void _tn_memcpy_uword( * Checks whether context switch is needed (that is, if currently running task * is not the highest-priority task in the $(TN_TASK_STATE_RUNNABLE) state) * - * @return `#TRUE` if context switch is needed + * @return `#TN_TRUE` if context switch is needed */ -static inline BOOL _tn_need_context_switch(void) +static inline TN_BOOL _tn_need_context_switch(void) { return (tn_curr_run_task != tn_next_task_to_run); } diff --git a/src/core/internal/_tn_tasks.h b/src/core/internal/_tn_tasks.h index 1b4a05d..4d05316 100644 --- a/src/core/internal/_tn_tasks.h +++ b/src/core/internal/_tn_tasks.h @@ -109,7 +109,7 @@ void _tn_task_clear_runnable(struct TN_Task *task); /** * Returns whether given task is in $(TN_TASK_STATE_RUNNABLE) state. */ -static inline BOOL _tn_task_is_runnable(struct TN_Task *task) +static inline TN_BOOL _tn_task_is_runnable(struct TN_Task *task) { return !!(task->task_state & TN_TASK_STATE_RUNNABLE); } @@ -126,7 +126,7 @@ static inline BOOL _tn_task_is_runnable(struct TN_Task *task) * Task to bring to the $(TN_TASK_STATE_WAIT) state * * @param wait_que - * Wait queue to put task in, may be `#NULL`. If not `#NULL`, task is + * Wait queue to put task in, may be `#TN_NULL`. If not `#TN_NULL`, task is * included in that list by `task_queue` member of `struct #TN_Task`. * * @param wait_reason @@ -160,7 +160,7 @@ void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc); * Returns whether given task is in $(TN_TASK_STATE_WAIT) state. * Note that this state could be combined with $(TN_TASK_STATE_SUSPEND) state. */ -static inline BOOL _tn_task_is_waiting(struct TN_Task *task) +static inline TN_BOOL _tn_task_is_waiting(struct TN_Task *task) { return !!(task->task_state & TN_TASK_STATE_WAIT); } @@ -192,7 +192,7 @@ void _tn_task_clear_suspended(struct TN_Task *task); * Returns whether given task is in $(TN_TASK_STATE_SUSPEND) state. * Note that this state could be combined with $(TN_TASK_STATE_WAIT) state. */ -static inline BOOL _tn_task_is_suspended(struct TN_Task *task) +static inline TN_BOOL _tn_task_is_suspended(struct TN_Task *task) { return !!(task->task_state & TN_TASK_STATE_SUSPEND); } @@ -222,7 +222,7 @@ void _tn_task_clear_dormant(struct TN_Task *task); /** * Returns whether given task is in $(TN_TASK_STATE_DORMANT) state. */ -static inline BOOL _tn_task_is_dormant(struct TN_Task *task) +static inline TN_BOOL _tn_task_is_dormant(struct TN_Task *task) { return !!(task->task_state & TN_TASK_STATE_DORMANT); } @@ -328,9 +328,9 @@ void _tn_task_set_last_rc_if_error(enum TN_RCode rc); /** * Check if mutex is locked by task. * - * @return TRUE if mutex is locked, FALSE otherwise. + * @return TN_TRUE if mutex is locked, TN_FALSE otherwise. */ -BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex); +TN_BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex); #endif /** @@ -346,7 +346,7 @@ BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex); * * @param callback * Callback function to call before wake task up, see - * `#_TN_CBBeforeTaskWaitComplete`. Can be `NULL`. + * `#_TN_CBBeforeTaskWaitComplete`. Can be `TN_NULL`. * * @param user_data_1 * Arbitrary data that is passed to the callback @@ -356,10 +356,10 @@ BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex); * * * @return - * - `TRUE` if queue is not empty and task has woken up - * - `FALSE` if queue is empty, so, no task to wake up + * - `TN_TRUE` if queue is not empty and task has woken up + * - `TN_FALSE` if queue is empty, so, no task to wake up */ -BOOL _tn_task_first_wait_complete( +TN_BOOL _tn_task_first_wait_complete( struct TN_ListItem *wait_queue, enum TN_RCode wait_rc, _TN_CBBeforeTaskWaitComplete *callback, @@ -378,7 +378,7 @@ BOOL _tn_task_first_wait_complete( * Checks whether given task object is valid * (actually, just checks against `id_task` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_task_is_valid( +static inline TN_BOOL _tn_task_is_valid( struct TN_Task *task ) { diff --git a/src/core/internal/_tn_timer.h b/src/core/internal/_tn_timer.h index d2aee4b..906417c 100644 --- a/src/core/internal/_tn_timer.h +++ b/src/core/internal/_tn_timer.h @@ -126,7 +126,7 @@ enum TN_RCode _tn_timer_set_func( * Actual worker function that is called by `#tn_timer_is_active()`. * Interrupts should be disabled when calling it. */ -BOOL _tn_timer_is_active(struct TN_Timer *timer); +TN_BOOL _tn_timer_is_active(struct TN_Timer *timer); /** * Actual worker function that is called by `#tn_timer_time_left()`. @@ -146,7 +146,7 @@ TN_Timeout _tn_timer_time_left(struct TN_Timer *timer); * Checks whether given timer object is valid * (actually, just checks against `id_timer` field, see `enum #TN_ObjId`) */ -static inline BOOL _tn_timer_is_valid( +static inline TN_BOOL _tn_timer_is_valid( struct TN_Timer *timer ) { diff --git a/src/core/tn_common.h b/src/core/tn_common.h index c875c80..3f631da 100644 --- a/src/core/tn_common.h +++ b/src/core/tn_common.h @@ -215,23 +215,23 @@ typedef unsigned long TN_Timeout; /// NULL pointer definition -#ifndef NULL -# define NULL ((void *)0) +#ifndef TN_NULL +# define TN_NULL ((void *)0) #endif /// boolean type definition -#ifndef BOOL -# define BOOL int +#ifndef TN_BOOL +# define TN_BOOL int #endif -/// `true` value definition for type `#BOOL` -#ifndef TRUE -# define TRUE (1 == 1) +/// `true` value definition for type `#TN_BOOL` +#ifndef TN_TRUE +# define TN_TRUE (1 == 1) #endif -/// `false` value definition for type `#BOOL` -#ifndef FALSE -# define FALSE (1 == 0) +/// `false` value definition for type `#TN_BOOL` +#ifndef TN_FALSE +# define TN_FALSE (1 == 0) #endif /** diff --git a/src/core/tn_dqueue.c b/src/core/tn_dqueue.c index 62607dd..7e80ca4 100644 --- a/src/core/tn_dqueue.c +++ b/src/core/tn_dqueue.c @@ -79,7 +79,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (dque == NULL){ + if (dque == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_dqueue_is_valid(dque)){ rc = TN_RC_INVALID_OBJ; @@ -96,7 +96,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (dque == NULL){ + if (dque == TN_NULL){ rc = TN_RC_WPARAM; } else if (items_cnt < 0 || _tn_dqueue_is_valid(dque)){ rc = TN_RC_WPARAM; @@ -109,7 +109,7 @@ static inline enum TN_RCode _check_param_read( void **pp_data ) { - return (pp_data == NULL) ? TN_RC_WPARAM : TN_RC_OK; + return (pp_data == TN_NULL) ? TN_RC_WPARAM : TN_RC_OK; } #else @@ -140,7 +140,7 @@ static enum TN_RCode _fifo_write(struct TN_DQueue *dque, void *p_data) //-- set flag in the connected event group (if any), // indicating that there are messages in the queue - _tn_eventgrp_link_manage(&dque->eventgrp_link, TRUE); + _tn_eventgrp_link_manage(&dque->eventgrp_link, TN_TRUE); } return rc; @@ -169,7 +169,7 @@ static enum TN_RCode _fifo_read(struct TN_DQueue *dque, void **pp_data) if (dque->filled_items_cnt == 0){ //-- clear flag in the connected event group (if any), // indicating that there are no messages in the queue - _tn_eventgrp_link_manage(&dque->eventgrp_link, FALSE); + _tn_eventgrp_link_manage(&dque->eventgrp_link, TN_FALSE); } } @@ -234,7 +234,7 @@ static enum TN_RCode _queue_send( if ( !_tn_task_first_wait_complete( &dque->wait_receive_list, TN_RC_OK, - _cb_before_task_wait_complete__send, p_data, NULL + _cb_before_task_wait_complete__send, p_data, TN_NULL ) ) { @@ -261,7 +261,7 @@ static enum TN_RCode _queue_receive( // wake the first one up, since there is room now. _tn_task_first_wait_complete( &dque->wait_send_list, TN_RC_OK, - _cb_before_task_wait_complete__receive_ok, dque, NULL + _cb_before_task_wait_complete__receive_ok, dque, TN_NULL ); break; @@ -271,7 +271,7 @@ static enum TN_RCode _queue_receive( // (that might happen if only dque->items_cnt is 0) if ( _tn_task_first_wait_complete( &dque->wait_send_list, TN_RC_OK, - _cb_before_task_wait_complete__receive_timeout, pp_data, NULL + _cb_before_task_wait_complete__receive_timeout, pp_data, TN_NULL ) ) { @@ -304,7 +304,7 @@ static enum TN_RCode _dqueue_job_perform( TN_Timeout timeout ) { - BOOL waited = FALSE; + TN_BOOL waited = TN_FALSE; void **pp_data = (void **)p_data; enum TN_RCode rc = _check_param_generic(dque); @@ -331,7 +331,7 @@ static enum TN_RCode _dqueue_job_perform( timeout ); - waited = TRUE; + waited = TN_TRUE; } break; @@ -346,7 +346,7 @@ static enum TN_RCode _dqueue_job_perform( timeout ); - waited = TRUE; + waited = TN_TRUE; } break; } @@ -449,7 +449,7 @@ enum TN_RCode tn_queue_create( _tn_eventgrp_link_reset(&dque->eventgrp_link); - if (dque->data_fifo == NULL){ + if (dque->data_fifo == TN_NULL){ dque->items_cnt = 0; } diff --git a/src/core/tn_dqueue.h b/src/core/tn_dqueue.h index d0a845a..58a8270 100644 --- a/src/core/tn_dqueue.h +++ b/src/core/tn_dqueue.h @@ -53,7 +53,7 @@ * element into the data queue). To use a data queue just for the synchronous * message passing, set size of the FIFO to 0. The data element to be sent and * received can be interpreted as a pointer or an integer and may have value 0 - * (`NULL`). + * (`TN_NULL`). * * For the useful pattern on how to use queue together with \ref tn_fmem.h * "fixed memory pool", refer to the example: `examples/queue`. Be sure @@ -111,7 +111,7 @@ struct TN_DQueue { struct TN_ListItem wait_receive_list; /// - /// array of `void *` to store data queue items. Can be `NULL`. + /// array of `void *` to store data queue items. Can be `TN_NULL`. void **data_fifo; /// /// capacity (total items count). Can be 0. @@ -167,7 +167,7 @@ struct TN_DQueueTaskWait { * * @param dque pointer to already allocated struct TN_DQueue. * @param data_fifo pointer to already allocated array of `void *` to store - * data queue items. Can be NULL. + * data queue items. Can be TN_NULL. * @param items_cnt capacity of queue * (count of elements in the `data_fifo` array) * Can be 0. diff --git a/src/core/tn_eventgrp.c b/src/core/tn_eventgrp.c index 990b3e6..1b492fb 100644 --- a/src/core/tn_eventgrp.c +++ b/src/core/tn_eventgrp.c @@ -71,7 +71,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (eventgrp == NULL){ + if (eventgrp == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_eventgrp_is_valid(eventgrp)){ rc = TN_RC_INVALID_OBJ; @@ -100,7 +100,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (eventgrp == NULL || _tn_eventgrp_is_valid(eventgrp)){ + if (eventgrp == TN_NULL || _tn_eventgrp_is_valid(eventgrp)){ rc = TN_RC_WPARAM; } @@ -115,7 +115,7 @@ static inline enum TN_RCode _check_param_create( // }}} -static BOOL _cond_check( +static TN_BOOL _cond_check( struct TN_EventGrp *eventgrp, enum TN_EGrpWaitMode wait_mode, TN_UWord wait_pattern @@ -124,7 +124,7 @@ static BOOL _cond_check( //-- interrupts should be disabled here _TN_BUG_ON( !TN_IS_INT_DISABLED() ); - BOOL cond = FALSE; + TN_BOOL cond = TN_FALSE; switch (wait_mode){ case TN_EVENTGRP_WMODE_OR: @@ -210,7 +210,7 @@ static enum TN_RCode _eventgrp_wait( //-- Check release condition if (_cond_check(eventgrp, wait_mode, wait_pattern)){ - if (p_flags_pattern != NULL){ + if (p_flags_pattern != TN_NULL){ *p_flags_pattern = eventgrp->pattern; } _clear_pattern_if_needed(eventgrp, wait_mode, wait_pattern); @@ -328,7 +328,7 @@ enum TN_RCode tn_eventgrp_wait( TN_Timeout timeout ) { - BOOL waited_for_event = FALSE; + TN_BOOL waited_for_event = TN_FALSE; enum TN_RCode rc = _check_param_generic(eventgrp); if (rc != TN_RC_OK){ @@ -350,7 +350,7 @@ enum TN_RCode tn_eventgrp_wait( TN_WAIT_REASON_EVENT, timeout ); - waited_for_event = TRUE; + waited_for_event = TN_TRUE; } #if TN_DEBUG @@ -367,7 +367,7 @@ enum TN_RCode tn_eventgrp_wait( //-- if wait result is TN_RC_OK, and p_flags_pattern is provided, // copy actual_pattern there - if (rc == TN_RC_OK && p_flags_pattern != NULL ){ + if (rc == TN_RC_OK && p_flags_pattern != TN_NULL ){ *p_flags_pattern = tn_curr_run_task->subsys_wait.eventgrp.actual_pattern; } @@ -537,7 +537,7 @@ enum TN_RCode _tn_eventgrp_link_reset( { enum TN_RCode rc = TN_RC_OK; - eventgrp_link->eventgrp = NULL; + eventgrp_link->eventgrp = TN_NULL; eventgrp_link->pattern = (0); return rc; @@ -549,7 +549,7 @@ enum TN_RCode _tn_eventgrp_link_reset( */ enum TN_RCode _tn_eventgrp_link_manage( struct TN_EGrpLink *eventgrp_link, - BOOL set + TN_BOOL set ) { //-- interrupts should be disabled here @@ -557,7 +557,7 @@ enum TN_RCode _tn_eventgrp_link_manage( enum TN_RCode rc = TN_RC_OK; - if (eventgrp_link->eventgrp != NULL){ + if (eventgrp_link->eventgrp != TN_NULL){ _eventgrp_modify( eventgrp_link->eventgrp, (set ? TN_EVENTGRP_OP_SET : TN_EVENTGRP_OP_CLEAR), diff --git a/src/core/tn_eventgrp.h b/src/core/tn_eventgrp.h index 3940fe4..802f3cd 100644 --- a/src/core/tn_eventgrp.h +++ b/src/core/tn_eventgrp.h @@ -270,13 +270,13 @@ enum TN_RCode tn_eventgrp_delete(struct TN_EventGrp *eventgrp); * @param p_flags_pattern * Pointer to the `TN_UWord` variable in which actual event pattern * that caused task to stop waiting will be stored. - * May be `NULL`. + * May be `TN_NULL`. * @param timeout * refer to `#TN_Timeout` * * @return * * `#TN_RC_OK` if specified event is active (so the task can check - * variable pointed to by `p_flags_pattern` if it wasn't `NULL`). + * variable pointed to by `p_flags_pattern` if it wasn't `TN_NULL`). * * `#TN_RC_WCONTEXT` if called from wrong context; * * Other possible return codes depend on `timeout` value, * refer to `#TN_Timeout` diff --git a/src/core/tn_exch.c b/src/core/tn_exch.c index 5e2baed..7e49b35 100644 --- a/src/core/tn_exch.c +++ b/src/core/tn_exch.c @@ -84,7 +84,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (exch == NULL){ + if (exch == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_exch_is_valid(exch)){ rc = TN_RC_INVALID_OBJ; @@ -99,7 +99,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (exch == NULL){ + if (exch == TN_NULL){ rc = TN_RC_WPARAM; } else if (_tn_exch_is_valid(exch)){ rc = TN_RC_WPARAM; @@ -151,9 +151,9 @@ enum TN_RCode tn_exch_create( goto out; } - //-- basic check: data should not be NULL, + //-- basic check: data should not be TN_NULL, // and size should not be 0 - if (data == NULL || size == 0){ + if (data == TN_NULL || size == 0){ rc = TN_RC_WPARAM; goto out; } diff --git a/src/core/tn_exch.h b/src/core/tn_exch.h index a768849..0c791ef 100644 --- a/src/core/tn_exch.h +++ b/src/core/tn_exch.h @@ -115,7 +115,7 @@ struct TN_ExchLinkQueue { /// allocated for the message. /// /// NOTE: if the size of exchange item is <= `sizeof(void *)`, - /// fixed memory pool might be not used (`NULL`): then, data + /// fixed memory pool might be not used (`TN_NULL`): then, data /// will be passed by the queue only. /// /// If fixed memory pool is used, its size should match the size of diff --git a/src/core/tn_exch_link.c b/src/core/tn_exch_link.c index 27b696e..06a6fcf 100644 --- a/src/core/tn_exch_link.c +++ b/src/core/tn_exch_link.c @@ -77,7 +77,7 @@ static const struct TN_ExchLink_VTable _vtable = { .notify = _notify_error, .dtor = _dtor, }; -//static BOOL _vtable_initialized = FALSE; +//static TN_BOOL _vtable_initialized = TN_FALSE; @@ -102,7 +102,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (exch_link == NULL){ + if (exch_link == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_exch_link_is_valid(exch_link)){ rc = TN_RC_INVALID_OBJ; @@ -117,7 +117,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (exch_link == NULL){ + if (exch_link == TN_NULL){ rc = TN_RC_WPARAM; } else if (_tn_exch_link_is_valid(exch_link)){ rc = TN_RC_WPARAM; @@ -152,7 +152,7 @@ static void _vtable_init() _vtable.notify = _notify_error; _vtable.dtor = _dtor; - _vtable_initialized = TRUE; + _vtable_initialized = TN_TRUE; } } #endif diff --git a/src/core/tn_exch_link.h b/src/core/tn_exch_link.h index c97a71e..d8150f9 100644 --- a/src/core/tn_exch_link.h +++ b/src/core/tn_exch_link.h @@ -104,7 +104,7 @@ struct TN_ExchLink { struct TN_ListItem links_list_item; /// /// Pointer to `#TN_Exch` object to which this link is added. - /// If not added to any exchange object, it is `NULL`. + /// If not added to any exchange object, it is `TN_NULL`. struct TN_Exch *exch; /// /// Pointer to the virtual methods table diff --git a/src/core/tn_exch_link_queue.c b/src/core/tn_exch_link_queue.c index dc0934e..2fa6fc5 100644 --- a/src/core/tn_exch_link_queue.c +++ b/src/core/tn_exch_link_queue.c @@ -109,7 +109,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (exch_link_queue == NULL){ + if (exch_link_queue == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_dqueue_is_valid(queue)){ rc = TN_RC_WPARAM; @@ -133,7 +133,7 @@ static enum TN_RCode _notify(struct TN_ExchLink *exch_link) struct TN_ExchLinkQueue *exch_link_queue = _tn_get_exch_link_queue_by_exch_link(exch_link); - void *p_msg = NULL; + void *p_msg = TN_NULL; rc = tn_is_task_context() ? tn_fmem_get(exch_link_queue->fmem, &p_msg, TN_WAIT_INFINITE) diff --git a/src/core/tn_exch_link_queue.h b/src/core/tn_exch_link_queue.h index c22352b..148faa5 100644 --- a/src/core/tn_exch_link_queue.h +++ b/src/core/tn_exch_link_queue.h @@ -82,7 +82,7 @@ struct TN_ExchLinkQueue { struct TN_DQueue *queue; /// /// A pointer to fixed-memory pool to get memory from. - /// Note: if data size is <= `sizeof(#TN_UWord)`, `fmem` might be `NULL`. + /// Note: if data size is <= `sizeof(#TN_UWord)`, `fmem` might be `TN_NULL`. struct TN_FMem *fmem; }; diff --git a/src/core/tn_fmem.c b/src/core/tn_fmem.c index 29c5923..734f921 100644 --- a/src/core/tn_fmem.c +++ b/src/core/tn_fmem.c @@ -74,7 +74,7 @@ static inline enum TN_RCode _check_param_fmem_create(struct TN_FMem *fmem) { enum TN_RCode rc = TN_RC_OK; - if (fmem == NULL){ + if (fmem == TN_NULL){ rc = TN_RC_WPARAM; } else if (_tn_fmem_is_valid(fmem)){ rc = TN_RC_WPARAM; @@ -87,7 +87,7 @@ static inline enum TN_RCode _check_param_fmem_delete(struct TN_FMem *fmem) { enum TN_RCode rc = TN_RC_OK; - if (fmem == NULL){ + if (fmem == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_fmem_is_valid(fmem)){ rc = TN_RC_INVALID_OBJ; @@ -103,7 +103,7 @@ static inline enum TN_RCode _check_param_job_perform( { enum TN_RCode rc = TN_RC_OK; - if (fmem == NULL || p_data == NULL){ + if (fmem == TN_NULL || p_data == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_fmem_is_valid(fmem)){ rc = TN_RC_INVALID_OBJ; @@ -130,7 +130,7 @@ static void _cb_before_task_wait_complete( static inline enum TN_RCode _fmem_get(struct TN_FMem *fmem, void **p_data) { enum TN_RCode rc; - void *ptr = NULL; + void *ptr = TN_NULL; if (fmem->free_blocks_cnt > 0){ ptr = fmem->free_list; @@ -152,7 +152,7 @@ static inline enum TN_RCode _fmem_release(struct TN_FMem *fmem, void *p_data) if ( !_tn_task_first_wait_complete( &fmem->wait_queue, TN_RC_OK, - _cb_before_task_wait_complete, p_data, NULL + _cb_before_task_wait_complete, p_data, TN_NULL ) ) { @@ -205,9 +205,9 @@ enum TN_RCode tn_fmem_create( goto out; } - //-- basic check: start_addr should not be NULL, + //-- basic check: start_addr should not be TN_NULL, // and blocks_cnt should be at least 2 - if (start_addr == NULL || blocks_cnt < 2){ + if (start_addr == TN_NULL || blocks_cnt < 2){ rc = TN_RC_WPARAM; goto out; } @@ -254,7 +254,7 @@ enum TN_RCode tn_fmem_create( p_tmp = (void **)p_block; p_block += fmem->block_size; } - *p_tmp = NULL; //-- Last memory block first cell contents - NULL + *p_tmp = TN_NULL; //-- Last memory block first cell contents - TN_NULL fmem->free_list = fmem->start_addr; fmem->free_blocks_cnt = fmem->blocks_cnt; @@ -309,7 +309,7 @@ enum TN_RCode tn_fmem_get( TN_Timeout timeout ) { - BOOL waited_for_data = FALSE; + TN_BOOL waited_for_data = TN_FALSE; enum TN_RCode rc = _check_param_job_perform(fmem, p_data); if (rc != TN_RC_OK){ @@ -329,7 +329,7 @@ enum TN_RCode tn_fmem_get( TN_WAIT_REASON_WFIXMEM, timeout ); - waited_for_data = TRUE; + waited_for_data = TN_TRUE; } TN_INT_RESTORE(); diff --git a/src/core/tn_list.c b/src/core/tn_list.c index ee3e181..78c8e42 100644 --- a/src/core/tn_list.c +++ b/src/core/tn_list.c @@ -50,7 +50,7 @@ void _tn_list_reset(struct TN_ListItem *list) /* * See comments in the header file tn_list.h */ -BOOL _tn_list_is_empty(struct TN_ListItem *list) +TN_BOOL _tn_list_is_empty(struct TN_ListItem *list) { return (list->next == list && list->prev == list); } @@ -88,14 +88,14 @@ struct TN_ListItem *_tn_list_remove_head(struct TN_ListItem *list) { //-- Remove and return an entry at the head of the queue. - struct TN_ListItem *entry = NULL; + struct TN_ListItem *entry = TN_NULL; - if (list != NULL && list->next != list){ + if (list != TN_NULL && list->next != list){ entry = list->next; entry->next->prev = list; list->next = entry->next; } else { - //-- NULL will be returned + //-- TN_NULL will be returned } return entry; @@ -142,14 +142,14 @@ void _tn_list_remove_entry(struct TN_ListItem *entry) /* * See comments in the header file tn_list.h */ -BOOL _tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry) +TN_BOOL _tn_list_contains_entry(struct TN_ListItem *list, struct TN_ListItem *entry) { - BOOL ret = FALSE; + TN_BOOL ret = TN_FALSE; struct TN_ListItem *item; _tn_list_for_each(item, list){ if (item == list){ - ret = TRUE; + ret = TN_TRUE; break; } } diff --git a/src/core/tn_mutex.c b/src/core/tn_mutex.c index 88c5c96..e532e11 100644 --- a/src/core/tn_mutex.c +++ b/src/core/tn_mutex.c @@ -96,7 +96,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (mutex == NULL){ + if (mutex == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_mutex_is_valid(mutex)){ rc = TN_RC_INVALID_OBJ; @@ -113,7 +113,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (mutex == NULL){ + if (mutex == TN_NULL){ rc = TN_RC_WPARAM; } else if (_tn_mutex_is_valid(mutex)){ rc = TN_RC_WPARAM; @@ -412,7 +412,7 @@ static void _check_deadlock_active(struct TN_Mutex *mutex, struct TN_Task *task) // tn_callback_deadlock_set()) NOTE: we should call this function // _after_ calling _link_deadlock_lists(), so that user may examine // mutexes and tasks involved in deadlock. - _tn_cry_deadlock(TRUE, mutex, task); + _tn_cry_deadlock(TN_TRUE, mutex, task); } else { //-- call this function again, recursively // @@ -451,7 +451,7 @@ static void _cry_deadlock_inactive(struct TN_Mutex *mutex, struct TN_Task *task) // tn_callback_deadlock_set()) NOTE: we should call this function // _before_ calling _unlink_deadlock_lists(), so that user may examine // mutexes and tasks involved in deadlock. - _tn_cry_deadlock(FALSE, mutex, task); + _tn_cry_deadlock(TN_FALSE, mutex, task); //-- unlink deadlock lists (for mutexes and tasks involved) _unlink_deadlock_lists(mutex, task); @@ -498,11 +498,11 @@ static inline void _add_curr_task_to_mutex_wait_queue( * * Remove given mutex from task's locked mutexes list, * * Set new priority of the task * (depending on its base_priority and other locked mutexes), - * * If no other tasks want to lock this mutex, set holder to NULL, + * * If no other tasks want to lock this mutex, set holder to TN_NULL, * otherwise grab first task from the mutex's wait_queue * and lock mutex by this task. * - * @returns TRUE if context switch is needed + * @returns TN_TRUE if context switch is needed * (that is, if there is some other task that waited for mutex, * and this task has highest priority now) */ @@ -521,8 +521,8 @@ static void _mutex_do_unlock(struct TN_Mutex * mutex) //-- Check for the task(s) that want to lock the mutex if (_tn_list_is_empty(&(mutex->wait_queue))){ //-- no more tasks want to lock the mutex, - // so, set holder to NULL and return. - mutex->holder = NULL; + // so, set holder to TN_NULL and return. + mutex->holder = TN_NULL; } else { //-- there are tasks that want to lock the mutex, // so, lock it by the first task in the queue @@ -548,9 +548,9 @@ static void _mutex_do_unlock(struct TN_Mutex * mutex) // so, special flag invented: priority_already_updated. // It's probably not so elegant, but I believe it is // acceptable tradeoff in the name of efficiency. - mutex->holder->priority_already_updated = TRUE; + mutex->holder->priority_already_updated = TN_TRUE; _tn_task_wait_complete(task, TN_RC_OK); - mutex->holder->priority_already_updated = FALSE; + mutex->holder->priority_already_updated = TN_FALSE; //-- lock mutex by it _mutex_do_lock(mutex, task); @@ -585,7 +585,7 @@ enum TN_RCode tn_mutex_create( #endif mutex->protocol = protocol; - mutex->holder = NULL; + mutex->holder = TN_NULL; mutex->ceil_priority = ceil_priority; mutex->cnt = 0; mutex->id_mutex = TN_ID_MUTEX; @@ -611,14 +611,14 @@ enum TN_RCode tn_mutex_delete(struct TN_Mutex *mutex) TN_INT_DIS_SAVE(); //-- mutex can be deleted if only it isn't held - if (mutex->holder != NULL && mutex->holder != tn_curr_run_task){ + if (mutex->holder != TN_NULL && mutex->holder != tn_curr_run_task){ rc = TN_RC_ILLEGAL_USE; } else { //-- Remove all tasks (if any) from mutex's wait queue _tn_wait_queue_notify_deleted(&(mutex->wait_queue)); - if (mutex->holder != NULL){ + if (mutex->holder != TN_NULL){ //-- If the mutex is locked _mutex_do_unlock(mutex); @@ -649,7 +649,7 @@ enum TN_RCode tn_mutex_delete(struct TN_Mutex *mutex) enum TN_RCode tn_mutex_lock(struct TN_Mutex *mutex, TN_Timeout timeout) { enum TN_RCode rc = _check_param_generic(mutex); - BOOL waited_for_mutex = FALSE; + TN_BOOL waited_for_mutex = TN_FALSE; if (rc != TN_RC_OK){ //-- just return rc as it is @@ -675,7 +675,7 @@ enum TN_RCode tn_mutex_lock(struct TN_Mutex *mutex, TN_Timeout timeout) //-- base priority of current task higher rc = TN_RC_ILLEGAL_USE; - } else if (mutex->holder == NULL){ + } else if (mutex->holder == TN_NULL){ //-- mutex is not locked, let's lock it //-- TODO: probably, we should add special flat to _mutex_do_lock, @@ -698,7 +698,7 @@ enum TN_RCode tn_mutex_lock(struct TN_Mutex *mutex, TN_Timeout timeout) //-- timeout specified, so, wait until mutex is free or timeout expired _add_curr_task_to_mutex_wait_queue(mutex, timeout); - waited_for_mutex = TRUE; + waited_for_mutex = TN_TRUE; //-- rc will be set later to tn_curr_run_task->task_wait_rc; } diff --git a/src/core/tn_sem.c b/src/core/tn_sem.c index 1f5338e..e7c8f2c 100644 --- a/src/core/tn_sem.c +++ b/src/core/tn_sem.c @@ -69,7 +69,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (sem == NULL){ + if (sem == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_sem_is_valid(sem)){ rc = TN_RC_INVALID_OBJ; @@ -89,7 +89,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (sem == NULL){ + if (sem == TN_NULL){ rc = TN_RC_WPARAM; } else if (0 || _tn_sem_is_valid(sem) @@ -125,7 +125,7 @@ static inline enum TN_RCode _sem_job_perform( ) { enum TN_RCode rc = _check_param_generic(sem); - BOOL waited_for_sem = FALSE; + TN_BOOL waited_for_sem = TN_FALSE; if (rc != TN_RC_OK){ //-- just return rc as it is @@ -144,11 +144,11 @@ static inline enum TN_RCode _sem_job_perform( ); //-- rc will be set later thanks to waited_for_sem - waited_for_sem = TRUE; + waited_for_sem = TN_TRUE; } #if TN_DEBUG - //-- if we're going to wait, _tn_need_context_switch() must return TRUE + //-- if we're going to wait, _tn_need_context_switch() must return TN_TRUE if (!_tn_need_context_switch() && waited_for_sem){ _TN_FATAL_ERROR(""); } @@ -201,7 +201,7 @@ static inline enum TN_RCode _sem_signal(struct TN_Sem *sem) //-- wake up first (if any) task from the semaphore wait queue if ( !_tn_task_first_wait_complete( &sem->wait_queue, TN_RC_OK, - NULL, NULL, NULL + TN_NULL, TN_NULL, TN_NULL ) ) { diff --git a/src/core/tn_sys.c b/src/core/tn_sys.c index 3ca99f9..255222e 100644 --- a/src/core/tn_sys.c +++ b/src/core/tn_sys.c @@ -103,13 +103,13 @@ static void _idle_task_body(void * par); /** * Pointer to user idle loop function */ -TN_CBIdle *tn_callback_idle_hook = NULL; +TN_CBIdle *tn_callback_idle_hook = TN_NULL; /** * User-provided callback function that is called whenever * event occurs (say, deadlock becomes active or inactive) */ -TN_CBDeadlock *tn_callback_deadlock = NULL; +TN_CBDeadlock *tn_callback_deadlock = TN_NULL; @@ -181,7 +181,7 @@ static inline enum TN_RCode _idle_task_create( idle_task_stack, //-- task stack idle_task_stack_size, //-- task stack size // (in int, not bytes) - NULL, //-- task function parameter + TN_NULL, //-- task function parameter (TN_TASK_CREATE_OPT_IDLE) //-- Creation option ); } @@ -233,8 +233,8 @@ void tn_sys_start( tn_int_nest_count = 0; //-- reset pointers to currently running task and next task to run - tn_next_task_to_run = NULL; - tn_curr_run_task = NULL; + tn_next_task_to_run = TN_NULL; + tn_curr_run_task = TN_NULL; //-- remember user-provided callbacks tn_callback_idle_hook = cb_idle; @@ -466,7 +466,7 @@ enum TN_StateFlag _tn_sys_state_flags_clear(enum TN_StateFlag flags) /** * See comments in the file _tn_sys.h */ -void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task) +void _tn_cry_deadlock(TN_BOOL active, struct TN_Mutex *mutex, struct TN_Task *task) { if (active){ if (tn_deadlocks_cnt == 0){ @@ -482,7 +482,7 @@ void _tn_cry_deadlock(BOOL active, struct TN_Mutex *mutex, struct TN_Task *task) } } - if (tn_callback_deadlock != NULL){ + if (tn_callback_deadlock != TN_NULL){ tn_callback_deadlock(active, mutex, task); } diff --git a/src/core/tn_sys.h b/src/core/tn_sys.h index 098e89b..02851d7 100644 --- a/src/core/tn_sys.h +++ b/src/core/tn_sys.h @@ -195,7 +195,7 @@ typedef void (TN_CBIdle)(void); * by means of `task->deadlock_list`. */ typedef void (TN_CBDeadlock)( - BOOL active, + TN_BOOL active, struct TN_Mutex *mutex, struct TN_Task *task ); @@ -367,13 +367,13 @@ enum TN_Context tn_sys_context_get(void); * $(TN_CALL_FROM_MAIN) * $(TN_LEGEND_LINK) * - * @return `TRUE` if current system context is `#TN_CONTEXT_TASK`, - * `FALSE` otherwise. + * @return `TN_TRUE` if current system context is `#TN_CONTEXT_TASK`, + * `TN_FALSE` otherwise. * * @see `tn_sys_context_get()` * @see `enum #TN_Context` */ -static inline BOOL tn_is_task_context(void) +static inline TN_BOOL tn_is_task_context(void) { return (tn_sys_context_get() == TN_CONTEXT_TASK); } @@ -386,13 +386,13 @@ static inline BOOL tn_is_task_context(void) * $(TN_CALL_FROM_MAIN) * $(TN_LEGEND_LINK) * - * @return `TRUE` if current system context is `#TN_CONTEXT_ISR`, - * `FALSE` otherwise. + * @return `TN_TRUE` if current system context is `#TN_CONTEXT_ISR`, + * `TN_FALSE` otherwise. * * @see `tn_sys_context_get()` * @see `enum #TN_Context` */ -static inline BOOL tn_is_isr_context(void) +static inline TN_BOOL tn_is_isr_context(void) { return (tn_sys_context_get() == TN_CONTEXT_ISR); } diff --git a/src/core/tn_tasks.c b/src/core/tn_tasks.c index 71d33f7..fc26ab5 100644 --- a/src/core/tn_tasks.c +++ b/src/core/tn_tasks.c @@ -75,7 +75,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (task == NULL){ + if (task == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_task_is_valid(task)){ rc = TN_RC_INVALID_OBJ; @@ -117,7 +117,7 @@ static inline void _init_deadlock_list(struct TN_Task *task) * Looks for first runnable task with highest priority, * set tn_next_task_to_run to it. * - * @return TRUE if tn_next_task_to_run was changed, FALSE otherwise. + * @return `TN_TRUE` if tn_next_task_to_run was changed, `TN_FALSE` otherwise. */ static void _find_next_task_to_run(void) { @@ -256,12 +256,12 @@ static inline enum TN_RCode _task_job_iperform( } /** - * Returns TRUE if there are no more items in the runqueue for given priority, - * FALSE otherwise. + * Returns TN_TRUE if there are no more items in the runqueue for given priority, + * TN_FALSE otherwise. */ -static inline BOOL _remove_entry_from_ready_queue(struct TN_ListItem *list_node, int priority) +static inline TN_BOOL _remove_entry_from_ready_queue(struct TN_ListItem *list_node, int priority) { - BOOL ret; + TN_BOOL ret; //-- remove given list_node from the queue _tn_list_remove_entry(list_node); @@ -390,9 +390,9 @@ enum TN_RCode tn_task_create( if (0 || (priority < 0 || priority > (TN_PRIORITIES_CNT - 1)) || task_stack_size < TN_MIN_STACK_SIZE - || task_func == NULL - || task == NULL - || task_stack_low_addr == NULL + || task_func == TN_NULL + || task == TN_NULL + || task_stack_low_addr == TN_NULL || _tn_task_is_valid(task) ) { @@ -429,7 +429,7 @@ enum TN_RCode tn_task_create( task->task_wait_reason = TN_WAIT_REASON_NONE; task->task_wait_rc = TN_RC_OK; - task->pwait_queue = NULL; + task->pwait_queue = TN_NULL; //-- fill all task stack space by #TN_FILL_STACK_VAL { @@ -562,7 +562,7 @@ enum TN_RCode tn_task_sleep(TN_Timeout timeout) TN_INT_DIS_SAVE(); - _tn_task_curr_to_wait_action(NULL, TN_WAIT_REASON_SLEEP, timeout); + _tn_task_curr_to_wait_action(TN_NULL, TN_WAIT_REASON_SLEEP, timeout); TN_INT_RESTORE(); _tn_context_switch_pend_if_needed(); @@ -806,7 +806,7 @@ void _tn_task_set_runnable(struct TN_Task * task) } #endif - //BOOL ret = FALSE; + //TN_BOOL ret = TN_FALSE; int priority; priority = task->priority; @@ -818,7 +818,7 @@ void _tn_task_set_runnable(struct TN_Task * task) //-- less value - greater priority, so '<' operation is used here if (priority < tn_next_task_to_run->priority){ tn_next_task_to_run = task; - //ret = TRUE; + //ret = TN_TRUE; } //return ret; @@ -841,7 +841,7 @@ void _tn_task_clear_runnable(struct TN_Task *task) } #endif - //BOOL ret = FALSE; + //TN_BOOL ret = TN_FALSE; int priority; priority = task->priority; @@ -865,7 +865,7 @@ void _tn_task_clear_runnable(struct TN_Task *task) // so we should select new next task to run tn_next_task_to_run = _tn_get_task_by_tsk_queue(tn_ready_list[priority].next); - //-- tn_next_task_to_run was just altered, so, we should return TRUE + //-- tn_next_task_to_run was just altered, so, we should return TN_TRUE } } @@ -897,11 +897,11 @@ void _tn_task_set_waiting( task->task_wait_reason = wait_reason; //task->tick_count = timeout; - task->waited = TRUE; + task->waited = TN_TRUE; //--- Add to the wait queue - FIFO - if (wait_que != NULL){ + if (wait_que != TN_NULL){ _tn_list_add_tail(wait_que, &(task->task_queue)); task->pwait_queue = wait_que; } else { @@ -929,7 +929,7 @@ void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc) _TN_FATAL_ERROR(""); } - if (_tn_list_is_empty(&task->task_queue) != (task->pwait_queue == NULL)){ + if (_tn_list_is_empty(&task->task_queue) != (task->pwait_queue == TN_NULL)){ _TN_FATAL_ERROR("task_queue and pwait_queue are out of sync"); } @@ -951,7 +951,7 @@ void _tn_task_clear_waiting(struct TN_Task *task, enum TN_RCode wait_rc) // handle priorities of other involved tasks. _on_task_wait_complete(task); - task->pwait_queue = NULL; + task->pwait_queue = TN_NULL; task->task_wait_rc = wait_rc; //-- if timer is active (i.e. task waits for timeout), @@ -1054,7 +1054,7 @@ enum TN_RCode _tn_task_activate(struct TN_Task *task) /** * See comment in the _tn_tasks.h file */ -BOOL _tn_task_first_wait_complete( +TN_BOOL _tn_task_first_wait_complete( struct TN_ListItem *wait_queue, enum TN_RCode wait_rc, _TN_CBBeforeTaskWaitComplete *callback, @@ -1062,7 +1062,7 @@ BOOL _tn_task_first_wait_complete( void *user_data_2 ) { - BOOL ret = FALSE; + TN_BOOL ret = TN_FALSE; if (!(_tn_list_is_empty(wait_queue))){ struct TN_Task *task; @@ -1072,7 +1072,7 @@ BOOL _tn_task_first_wait_complete( task = _tn_list_first_entry(wait_queue, typeof(*task), task_queue); //-- call provided callback (if any) - if (callback != NULL){ + if (callback != TN_NULL){ callback(task, user_data_1, user_data_2); } @@ -1080,7 +1080,7 @@ BOOL _tn_task_first_wait_complete( _tn_task_wait_complete(task, wait_rc); //-- indicate that some task has been woken up - ret = TRUE; + ret = TN_TRUE; } return ret; @@ -1139,14 +1139,14 @@ void _tn_task_set_last_rc_if_error(enum TN_RCode rc) /** * See comment in the _tn_tasks.h file */ -BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex) +TN_BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex) { - BOOL ret = FALSE; + TN_BOOL ret = TN_FALSE; struct TN_Mutex *tmp_mutex; _tn_list_for_each_entry(tmp_mutex, &(task->mutex_queue), mutex_queue){ if (tmp_mutex == mutex){ - ret = TRUE; + ret = TN_TRUE; break; } } diff --git a/src/core/tn_tasks.h b/src/core/tn_tasks.h index cd372dd..0977c45 100644 --- a/src/core/tn_tasks.h +++ b/src/core/tn_tasks.h @@ -344,7 +344,7 @@ struct TN_Task { * MY_TASK_PRIORITY, * my_task_stack, * MY_TASK_STACK_SIZE, - * NULL, //-- parameter isn't used + * TN_NULL, //-- parameter isn't used * TN_TASK_CREATE_OPT_START //-- start task on creation * ); * diff --git a/src/core/tn_timer.c b/src/core/tn_timer.c index af86401..48a5652 100644 --- a/src/core/tn_timer.c +++ b/src/core/tn_timer.c @@ -107,7 +107,7 @@ static inline enum TN_RCode _check_param_generic( { enum TN_RCode rc = TN_RC_OK; - if (timer == NULL){ + if (timer == TN_NULL){ rc = TN_RC_WPARAM; } else if (!_tn_timer_is_valid(timer)){ rc = TN_RC_INVALID_OBJ; @@ -123,7 +123,7 @@ static inline enum TN_RCode _check_param_create( { enum TN_RCode rc = TN_RC_OK; - if (timer == NULL){ + if (timer == TN_NULL){ rc = TN_RC_WPARAM; } else if (_tn_timer_is_valid(timer)){ rc = TN_RC_WPARAM; @@ -243,7 +243,7 @@ enum TN_RCode tn_timer_set_func( /* * See comments in the header file (tn_timer.h) */ -enum TN_RCode tn_timer_is_active(struct TN_Timer *timer, BOOL *p_is_active) +enum TN_RCode tn_timer_is_active(struct TN_Timer *timer, TN_BOOL *p_is_active) { int sr_saved; enum TN_RCode rc = _check_param_generic(timer); @@ -510,7 +510,7 @@ enum TN_RCode _tn_timer_set_func( { enum TN_RCode rc = TN_RC_OK; - if (func == NULL){ + if (func == TN_NULL){ rc = TN_RC_WPARAM; } else { timer->func = func; @@ -523,7 +523,7 @@ enum TN_RCode _tn_timer_set_func( /** * See comments in the _tn_timer.h file. */ -BOOL _tn_timer_is_active(struct TN_Timer *timer) +TN_BOOL _tn_timer_is_active(struct TN_Timer *timer) { #if TN_DEBUG //-- interrupts should be disabled here diff --git a/src/core/tn_timer.h b/src/core/tn_timer.h index aeabe30..58dd7ab 100644 --- a/src/core/tn_timer.h +++ b/src/core/tn_timer.h @@ -241,7 +241,7 @@ struct TN_Timer { * @param timer * Pointer to already allocated `struct TN_Timer` * @param func - * Function to be called by timer, can't be `NULL`. See `TN_TimerFunc()` + * Function to be called by timer, can't be `TN_NULL`. See `TN_TimerFunc()` * @param p_user_data * User data pointer that is given to user-provided `func`. * @@ -330,7 +330,7 @@ enum TN_RCode tn_timer_cancel(struct TN_Timer *timer); * @param timer * Pointer to timer * @param func - * Function to be called by timer, can't be `NULL`. See `TN_TimerFunc()` + * Function to be called by timer, can't be `TN_NULL`. See `TN_TimerFunc()` * @param p_user_data * User data pointer that is given to user-provided `func`. * @@ -354,13 +354,13 @@ enum TN_RCode tn_timer_set_func( * @param timer * Pointer to timer * @param p_is_active - * Pointer to `#BOOL` variable in which resulting value should be stored + * Pointer to `#TN_BOOL` variable in which resulting value should be stored * * @return * * `#TN_RC_OK` if operation was successfull; * * `#TN_RC_WPARAM` if wrong params were given. */ -enum TN_RCode tn_timer_is_active(struct TN_Timer *timer, BOOL *p_is_active); +enum TN_RCode tn_timer_is_active(struct TN_Timer *timer, TN_BOOL *p_is_active); /** * Returns how many $(TN_SYS_TIMER_LINK) ticks (at most) is left for the timer From 9b632bf39b712e96e70464502ababe28c2b663e5 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 19:33:36 +0300 Subject: [PATCH 23/96] exchange object draft was moved to tmp_src directory for now --- src/arch/pic32/tneokernel.X/nbproject/configurations.xml | 2 -- {src => stuff/tmp_src}/core/internal/_tn_exch.h | 0 {src => stuff/tmp_src}/core/internal/_tn_exch_link.h | 0 {src => stuff/tmp_src}/core/tn_exch.c | 0 {src => stuff/tmp_src}/core/tn_exch.h | 0 {src => stuff/tmp_src}/core/tn_exch_link.c | 0 {src => stuff/tmp_src}/core/tn_exch_link.h | 0 {src => stuff/tmp_src}/core/tn_exch_link_queue.c | 0 {src => stuff/tmp_src}/core/tn_exch_link_queue.h | 0 9 files changed, 2 deletions(-) rename {src => stuff/tmp_src}/core/internal/_tn_exch.h (100%) rename {src => stuff/tmp_src}/core/internal/_tn_exch_link.h (100%) rename {src => stuff/tmp_src}/core/tn_exch.c (100%) rename {src => stuff/tmp_src}/core/tn_exch.h (100%) rename {src => stuff/tmp_src}/core/tn_exch_link.c (100%) rename {src => stuff/tmp_src}/core/tn_exch_link.h (100%) rename {src => stuff/tmp_src}/core/tn_exch_link_queue.c (100%) rename {src => stuff/tmp_src}/core/tn_exch_link_queue.h (100%) diff --git a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml index 64b858f..0d33c97 100644 --- a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml +++ b/src/arch/pic32/tneokernel.X/nbproject/configurations.xml @@ -28,8 +28,6 @@ ../../../core/tn_eventgrp.c ../../../core/tn_fmem.c ../../../core/tn_timer.c - ../../../core/tn_exch.c - ../../../core/tn_exch_link_queue.c Date: Mon, 27 Oct 2014 19:39:29 +0300 Subject: [PATCH 24/96] docs: removed links to exchange, missing param comment added --- src/arch/tn_arch.h | 6 ++++-- stuff/doc_pages/mainpage.dox | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/arch/tn_arch.h b/src/arch/tn_arch.h index d1e286e..8cbb050 100644 --- a/src/arch/tn_arch.h +++ b/src/arch/tn_arch.h @@ -118,9 +118,9 @@ void tn_arch_sr_restore(TN_UWord sr); * used for storing the new data. Instead, it is the *previous* address. * * @param stack_low_address - * start address of the stack array. + * Start address of the stack array. * @param stack_size - * size of the stack in `#TN_UWord`-s, not in bytes. + * Size of the stack in `#TN_UWord`-s, not in bytes. */ TN_UWord *_tn_arch_stack_top_get( TN_UWord *stack_low_address, @@ -144,6 +144,8 @@ TN_UWord *_tn_arch_stack_top_get( * Pointer to task body function. * @param stack_top * Top of the stack, returned by `_tn_arch_stack_top_get()`. + * @param stack_size + * Size of the stack in `#TN_UWord`-s, not in bytes. * @param param * User-provided parameter for task body function. * diff --git a/stuff/doc_pages/mainpage.dox b/stuff/doc_pages/mainpage.dox index f99783c..0a39bea 100644 --- a/stuff/doc_pages/mainpage.dox +++ b/stuff/doc_pages/mainpage.dox @@ -42,7 +42,6 @@ API reference: - \ref tn_fmem.h "Fixed-memory blocks pool" - \ref tn_eventgrp.h "Event groups" - \ref tn_dqueue.h "Data queues" - - \ref tn_exch.h "Exchange" - \ref tn_timer.h "Timers" From 9c3389614a0a34bded19e353058e0341e738d39b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 19:41:34 +0300 Subject: [PATCH 25/96] removed inclusion of core/tn_exch.h from tn.h --- src/tn.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tn.h b/src/tn.h index 0a0943d..099e17f 100644 --- a/src/tn.h +++ b/src/tn.h @@ -56,7 +56,6 @@ #include "core/tn_mutex.h" #include "core/tn_sem.h" #include "core/tn_tasks.h" -#include "core/tn_exch.h" #include "core/tn_timer.h" From c5cec2d3b5a04d40e3523b359b53b5bc820bdb9b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 27 Oct 2014 21:14:01 +0300 Subject: [PATCH 26/96] pic24: exch files removed from the project --- .../pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml index 252d7a1..8f8be5c 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml @@ -26,8 +26,6 @@ ../../../core/tn_eventgrp.c ../../../core/tn_fmem.c ../../../core/tn_timer.c - ../../../core/tn_exch.c - ../../../core/tn_exch_link_queue.c Date: Mon, 27 Oct 2014 22:04:16 +0300 Subject: [PATCH 27/96] enum TN_ObjId: all values casted to (unsigned int), so that it will work on 16-bit platforms too --- src/core/tn_common.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/core/tn_common.h b/src/core/tn_common.h index 3f631da..881101b 100644 --- a/src/core/tn_common.h +++ b/src/core/tn_common.h @@ -83,17 +83,18 @@ extern "C" { /*}*/ /** * Magic number for object validity verification + * TODO: use TN_UWord here instead of unsigned int */ enum TN_ObjId { - TN_ID_TASK = 0x47ABCF69, //!< id for tasks - TN_ID_SEMAPHORE = 0x6FA173EB, //!< id for semaphores - TN_ID_EVENTGRP = 0x5E224F25, //!< id for event groups - TN_ID_DATAQUEUE = 0x8C8A6C89, //!< id for data queues - TN_ID_FSMEMORYPOOL = 0x26B7CE8B, //!< id for fixed memory pools - TN_ID_MUTEX = 0x17129E45, //!< id for mutexes - TN_ID_TIMER = 0x9A937FBC, //!< id for timers - TN_ID_EXCHANGE = 0x32b7c072, //!< id for exchange objects - TN_ID_EXCHANGE_LINK = 0x24d36f35, //!< id for exchange objects + TN_ID_TASK = (unsigned int)0x47ABCF69, //!< id for tasks + TN_ID_SEMAPHORE = (unsigned int)0x6FA173EB, //!< id for semaphores + TN_ID_EVENTGRP = (unsigned int)0x5E224F25, //!< id for event groups + TN_ID_DATAQUEUE = (unsigned int)0x8C8A6C89, //!< id for data queues + TN_ID_FSMEMORYPOOL = (unsigned int)0x26B7CE8B, //!< id for fixed memory pools + TN_ID_MUTEX = (unsigned int)0x17129E45, //!< id for mutexes + TN_ID_TIMER = (unsigned int)0x9A937FBC, //!< id for timers + TN_ID_EXCHANGE = (unsigned int)0x32b7c072, //!< id for exchange objects + TN_ID_EXCHANGE_LINK = (unsigned int)0x24d36f35, //!< id for exchange objects }; /** From 19bc3e9c8477748fa6c32d2d4d033e93159bdb5d Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 28 Oct 2014 13:43:01 +0300 Subject: [PATCH 28/96] pic24: when stack is being initialized, set PSV bit in CORCON register --- src/arch/pic24_dspic/tn_arch_pic24_c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index f183af9..224cb8b 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -74,7 +74,7 @@ TN_UWord *_tn_arch_stack_init( *(stack_top++) = 0x0101; // W01 *(stack_top++) = 0; // RCOUNT *(stack_top++) = 0; // TBLPAG - *(stack_top++) = 0; // CORCON + *(stack_top++) = 0x04; // CORCON TODO: take from real CORCON value *(stack_top++) = 0; // PSVPAG *(stack_top++) = (TN_UWord)p_splim; // SPLIM From f2c1fe30c19d6cd628581ba586a8e68b1f2bc070 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 28 Oct 2014 16:16:04 +0300 Subject: [PATCH 29/96] working on isr macro, for now this macro just sets internal kernel flag that isr is active --- src/arch/pic24_dspic/tn_arch_pic24.S | 15 +- src/arch/pic24_dspic/tn_arch_pic24.h | 185 ++++++------------------- src/arch/pic24_dspic/tn_arch_pic24_c.c | 8 ++ 3 files changed, 49 insertions(+), 159 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 897d44c..405732c 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -41,12 +41,12 @@ .extern tn_curr_run_task .extern tn_next_task_to_run .extern IFS0 + .extern _tn_p24_dspic_inside_isr /* Public functions declared in this file */ .global __tn_arch_context_switch_now_nosave .global __tn_arch_context_switch_pend - .global __tn_arch_inside_isr .global __tn_arch_is_int_disabled .global _tn_arch_sr_save_int_dis .global _tn_arch_sr_restore @@ -219,19 +219,6 @@ _tn_arch_sr_restore: * *----------------------------------------------------------------------------*/ -__tn_arch_inside_isr: - /* TODO: optimize */ - mov #0, W0 - - btsc _SR, #5 - mov #1, W0 - btsc _SR, #6 - mov #1, W0 - btsc _SR, #7 - mov #1, W0 - - return - __tn_arch_is_int_disabled: /* TODO: optimize */ diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 38475e9..5ba25ca 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -262,153 +262,48 @@ typedef unsigned int TN_UWord; // --------------------------------------------------------------------------- -/** - * Interrupt handler wrapper macro for software context saving. - * - * Usage looks like the following: - * - * tn_soft_isr(_TIMER_1_VECTOR) - * { - * INTClearFlag(INT_T1); - * - * //-- do something useful - * } - * - * Note that you should not use `__ISR(_TIMER_1_VECTOR)` macro for that. - * - * @param vec interrupt vector number, such as `_TIMER_1_VECTOR`, etc. - */ -#define tn_soft_isr(vec) \ -__attribute__((__noinline__)) void _func##vec(void); \ -void __attribute__((naked, nomips16)) \ - __attribute__((vector(vec))) \ - _isr##vec(void) \ -{ \ - asm volatile(".set push"); \ - asm volatile(".set mips32r2"); \ - asm volatile(".set nomips16"); \ - asm volatile(".set noreorder"); \ - asm volatile(".set noat"); \ - \ - asm volatile("rdpgpr $sp, $sp"); \ - \ - /* Increase interrupt nesting count */ \ - asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ - asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ - asm volatile("addiu $k1, $k1, 1"); \ - asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ - asm volatile("ori $k0, $zero, 1"); \ - asm volatile("bne $k1, $k0, 1f"); \ - \ - /* Swap stack pointers if nesting count is one */ \ - asm volatile("lui $k0, %hi(tn_user_sp)"); \ - asm volatile("sw $sp, %lo(tn_user_sp)($k0)"); \ - asm volatile("lui $k0, %hi(tn_int_sp)"); \ - asm volatile("lw $sp, %lo(tn_int_sp)($k0)"); \ - \ - asm volatile("1:"); \ - /* Save context on stack */ \ - asm volatile("addiu $sp, $sp, -92"); \ - asm volatile("mfc0 $k1, $14"); /* c0_epc*/ \ - asm volatile("mfc0 $k0, $12, 2"); /* c0_srsctl*/ \ - asm volatile("sw $k1, 84($sp)"); \ - asm volatile("sw $k0, 80($sp)"); \ - asm volatile("mfc0 $k1, $12"); /* c0_status*/ \ - asm volatile("sw $k1, 88($sp)"); \ - \ - /* Enable nested interrupts */ \ - asm volatile("mfc0 $k0, $13"); /* c0_cause*/ \ - asm volatile("ins $k1, $zero, 1, 15"); \ - asm volatile("ext $k0, $k0, 10, 6"); \ - asm volatile("ins $k1, $k0, 10, 6"); \ - asm volatile("mtc0 $k1, $12"); /* c0_status*/ \ - \ - /* Save caller-save registers on stack */ \ - asm volatile("sw $ra, 76($sp)"); \ - asm volatile("sw $t9, 72($sp)"); \ - asm volatile("sw $t8, 68($sp)"); \ - asm volatile("sw $t7, 64($sp)"); \ - asm volatile("sw $t6, 60($sp)"); \ - asm volatile("sw $t5, 56($sp)"); \ - asm volatile("sw $t4, 52($sp)"); \ - asm volatile("sw $t3, 48($sp)"); \ - asm volatile("sw $t2, 44($sp)"); \ - asm volatile("sw $t1, 40($sp)"); \ - asm volatile("sw $t0, 36($sp)"); \ - asm volatile("sw $a3, 32($sp)"); \ - asm volatile("sw $a2, 28($sp)"); \ - asm volatile("sw $a1, 24($sp)"); \ - asm volatile("sw $a0, 20($sp)"); \ - asm volatile("sw $v1, 16($sp)"); \ - asm volatile("sw $v0, 12($sp)"); \ - asm volatile("sw $at, 8($sp)"); \ - asm volatile("mfhi $v0"); \ - asm volatile("mflo $v1"); \ - asm volatile("sw $v0, 4($sp)"); \ - \ - /* Call ISR */ \ - asm volatile("la $t0, _func"#vec); \ - asm volatile("jalr $t0"); \ - asm volatile("sw $v1, 0($sp)"); \ - \ - /* Restore registers */ \ - asm volatile("lw $v1, 0($sp)"); \ - asm volatile("lw $v0, 4($sp)"); \ - asm volatile("mtlo $v1"); \ - asm volatile("mthi $v0"); \ - asm volatile("lw $at, 8($sp)"); \ - asm volatile("lw $v0, 12($sp)"); \ - asm volatile("lw $v1, 16($sp)"); \ - asm volatile("lw $a0, 20($sp)"); \ - asm volatile("lw $a1, 24($sp)"); \ - asm volatile("lw $a2, 28($sp)"); \ - asm volatile("lw $a3, 32($sp)"); \ - asm volatile("lw $t0, 36($sp)"); \ - asm volatile("lw $t1, 40($sp)"); \ - asm volatile("lw $t2, 44($sp)"); \ - asm volatile("lw $t3, 48($sp)"); \ - asm volatile("lw $t4, 52($sp)"); \ - asm volatile("lw $t5, 56($sp)"); \ - asm volatile("lw $t6, 60($sp)"); \ - asm volatile("lw $t7, 64($sp)"); \ - asm volatile("lw $t8, 68($sp)"); \ - asm volatile("lw $t9, 72($sp)"); \ - asm volatile("lw $ra, 76($sp)"); \ - \ - asm volatile("di"); \ - asm volatile("ehb"); \ - \ - /* Restore context */ \ - asm volatile("lw $k0, 84($sp)"); \ - asm volatile("mtc0 $k0, $14"); /* c0_epc */ \ - asm volatile("lw $k0, 80($sp)"); \ - asm volatile("mtc0 $k0, $12, 2"); /* c0_srsctl */ \ - asm volatile("addiu $sp, $sp, 92"); \ - \ - /* Decrease interrupt nesting count */ \ - asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ - asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ - asm volatile("addiu $k1, $k1, -1"); \ - asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ - asm volatile("bne $k1, $zero, 1f"); \ - asm volatile("lw $k1, -4($sp)"); \ - \ - /* Swap stack pointers if nesting count is zero */ \ - asm volatile("lui $k0, %hi(tn_int_sp)"); \ - asm volatile("sw $sp, %lo(tn_int_sp)($k0)"); \ - asm volatile("lui $k0, %hi(tn_user_sp)"); \ - asm volatile("lw $sp, %lo(tn_user_sp)($k0)"); \ - \ - asm volatile("1:"); \ - asm volatile("wrpgpr $sp, $sp"); \ - asm volatile("mtc0 $k1, $12"); /* c0_status */ \ - asm volatile("eret"); \ - \ - asm volatile(".set pop"); \ - \ -} __attribute((__noinline__)) void _func##vec(void) +extern volatile unsigned int __tn_p24_dspic_inside_isr; + + #define _avixInternalISR_Prologue \ +" push w0; \n" \ +" push w1; \n" \ +" push w15; \n" \ +" mov #__tn_p24_dspic_inside_isr, w0; \n" \ +" mov #1, w1; \n" \ +" mov w1, [w0]; \n" \ + + + #define _avixInternalISR_Activate \ + " rcall 1f; \n" + + #define _avixInternalISR_Epilogue \ +" mov #__tn_p24_dspic_inside_isr, w0; \n" \ +" mov #0, w1; \n" \ +" mov w1, [w0]; \n" \ +" pop w15; \n" \ +" pop w1; \n" \ +" pop w0; \n" \ +" retfie; \n" \ +"1: mov SR, w0; \n" \ +" mov.b w0, [w15-1]; " + + + #define _avixDeclareISRInternalUse(f,p,s) \ + \ + void __attribute__((__interrupt__ \ + ( \ + __preprologue__ \ + ( _avixInternalISR_Prologue \ + _avixInternalISR_Activate \ + _avixInternalISR_Epilogue \ + ) \ + ), \ + p, s)) f(void) + + +#define tn_soft_isr(f,p) _avixDeclareISRInternalUse(f,p,) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 224cb8b..407a498 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -36,6 +36,9 @@ #include "tn_tasks.h" +volatile unsigned int _tn_p24_dspic_inside_isr = 0; + + TN_UWord *_tn_arch_stack_top_get( TN_UWord *stack_low_address, @@ -94,6 +97,11 @@ void tn_arch_int_en(void) //TODO } +int _tn_arch_inside_isr(void) +{ + return _tn_p24_dspic_inside_isr; +} + //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- From bbb17d96ce4964ccbb23cde95470c568865b597b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 28 Oct 2014 16:36:02 +0300 Subject: [PATCH 30/96] pic24: _tn_arch_context_switch_now_nosave: set SPLIM to 0xffff before restoring context --- src/arch/pic24_dspic/tn_arch_pic24.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 405732c..69d2311 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -60,6 +60,13 @@ __tn_arch_context_switch_now_nosave: /* get new task's sp */ + /* set SPLIM to max: effectively, turn stack pointer limit off */ + + mov #0xffff, W0 + mov W0, _SPLIM + + /* ---- */ + mov #_tn_next_task_to_run, W1 ; W1 = &tn_next_task_to_run mov [W1], W1 ; W1 = tn_next_task_to_run mov #_tn_curr_run_task, W0 ; W0 = &tn_curr_run_task From 0ef196b8a0eb6ac881a0122c7b2a204363b36dc0 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 28 Oct 2014 17:33:06 +0300 Subject: [PATCH 31/96] TN_WAIT_INFINITE is ULONG_MAX, not UINT_MAX --- src/arch/example/tn_arch_example.h | 5 +++-- src/arch/pic24_dspic/tn_arch_pic24.h | 5 +++-- src/arch/pic32/tn_arch_pic32.h | 5 +++-- src/core/tn_timer.c | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/arch/example/tn_arch_example.h b/src/arch/example/tn_arch_example.h index b44db7e..a44473b 100644 --- a/src/arch/example/tn_arch_example.h +++ b/src/arch/example/tn_arch_example.h @@ -112,9 +112,10 @@ typedef unsigned int TN_UWord; #define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH /** - * Value for infinite waiting, usually matches `UINT_MAX` + * Value for infinite waiting, usually matches `ULONG_MAX`, + * because `#TN_Timeout` is declared as `unsigned long`. */ -#define TN_WAIT_INFINITE 0xFFFFFFFF +#define TN_WAIT_INFINITE (TN_Timeout)0xFFFFFFFF /** * Value for initializing the unused space of task's stack diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 5ba25ca..6c010cb 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -145,9 +145,10 @@ typedef unsigned int TN_UWord; #define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH /** - * Value for infinite waiting, usually matches `UINT_MAX` + * Value for infinite waiting, usually matches `ULONG_MAX`, + * because `#TN_Timeout` is declared as `unsigned long`. */ -#define TN_WAIT_INFINITE 0xFFFF +#define TN_WAIT_INFINITE (TN_Timeout)0xFFFFFFFF /** * Value for initializing the task's stack diff --git a/src/arch/pic32/tn_arch_pic32.h b/src/arch/pic32/tn_arch_pic32.h index 94c7237..ac7bd9c 100644 --- a/src/arch/pic32/tn_arch_pic32.h +++ b/src/arch/pic32/tn_arch_pic32.h @@ -145,9 +145,10 @@ typedef unsigned int TN_UWord; #define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH /** - * Value for infinite waiting, usually matches `UINT_MAX` + * Value for infinite waiting, usually matches `ULONG_MAX`, + * because `#TN_Timeout` is declared as `unsigned long`. */ -#define TN_WAIT_INFINITE 0xFFFFFFFF +#define TN_WAIT_INFINITE (TN_Timeout)0xFFFFFFFF /** * Value for initializing the task's stack diff --git a/src/core/tn_timer.c b/src/core/tn_timer.c index 48a5652..0f19950 100644 --- a/src/core/tn_timer.c +++ b/src/core/tn_timer.c @@ -90,7 +90,7 @@ struct TN_ListItem tn_timer_list__tick[ TN_TICK_LISTS_CNT ]; * @param timeout should be < TN_TICK_LISTS_CNT */ #define _TICK_LIST_INDEX(timeout) \ - ((tn_sys_time_count + timeout) & TN_TICK_LISTS_MASK) + (((TN_Timeout)tn_sys_time_count + timeout) & TN_TICK_LISTS_MASK) From 2edea6d245baab1f7809236799feb37f816569e4 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 28 Oct 2014 17:45:24 +0300 Subject: [PATCH 32/96] large code and data models --- .../nbproject/configurations.xml | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml index 8f8be5c..1661ea0 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml @@ -74,9 +74,9 @@ false - - - + + + @@ -89,7 +89,7 @@ - + @@ -115,6 +115,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 69e82f8604573cd7d747194723966c9e1560db1d Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 28 Oct 2014 19:29:39 +0300 Subject: [PATCH 33/96] switch from C30 to XC16 --- .../nbproject/configurations.xml | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml index 1661ea0..75513fb 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml @@ -47,8 +47,8 @@ ICD3PlatformTool - C30 - 3_30 + XC16 + 1.21 2 @@ -90,12 +90,32 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -107,6 +127,7 @@ + @@ -115,6 +136,7 @@ + @@ -125,13 +147,27 @@ + + + + + + + + + + + + + + @@ -145,9 +181,15 @@ + + + + + + From f0138ec83f62783e4947b1ccd2a8c6b400189a78 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Wed, 29 Oct 2014 02:36:17 +0300 Subject: [PATCH 34/96] added _tn_arch_sys_init(), PIC32 interrupt-related variables moved to arch/pic32 subdir --- src/arch/pic32/tn_arch_pic32.c | 62 +++++++++++++++++++++--- src/arch/pic32/tn_arch_pic32.h | 87 +++++++++++++++++++++++----------- src/arch/tn_arch.h | 8 +++- src/core/internal/_tn_sys.h | 12 ----- src/core/tn_sys.c | 16 ++----- 5 files changed, 125 insertions(+), 60 deletions(-) diff --git a/src/arch/pic32/tn_arch_pic32.c b/src/arch/pic32/tn_arch_pic32.c index 255a459..0b51c18 100644 --- a/src/arch/pic32/tn_arch_pic32.c +++ b/src/arch/pic32/tn_arch_pic32.c @@ -34,10 +34,26 @@ * ******************************************************************************/ +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + #include "tn_tasks.h" + + +/******************************************************************************* + * EXTERNAL DATA + ******************************************************************************/ + extern unsigned long _gp; + + +/******************************************************************************* + * EXTERNAL FUNCTION PROTOTYPES + ******************************************************************************/ + /** * Self-check for the application that uses TNeoKernel: * @@ -59,6 +75,45 @@ extern int _you_should_add_file___tn_arch_pic32_int_vec1_S___to_the_project(void); + + +/******************************************************************************* + * PROTECTED DATA + ******************************************************************************/ + +/* + * For comments on these variables, see the file tn_arch_pic32.h + */ + +volatile int tn_p32_int_nest_count; +void *tn_p32_user_sp; +void *tn_p32_int_sp; + + + + +/******************************************************************************* + * IMPLEMENTATION + ******************************************************************************/ + +void _tn_arch_sys_init( + TN_UWord *int_stack, + unsigned int int_stack_size + ) +{ + //-- reset interrupt nesting count + tn_p32_int_nest_count = 0; + + //-- set interrupt's top of the stack + tn_p32_int_sp = _tn_arch_stack_top_get( + int_stack, + int_stack_size + ); +} + + + + //---------------------------------------------------------------------------- // Context layout // @@ -172,8 +227,6 @@ TN_UWord *_tn_arch_stack_init( return stack_top; } -//_____________________________________________________________________________ -// void tn_arch_int_dis(void) { __builtin_disable_interrupts(); @@ -185,7 +238,4 @@ void tn_arch_int_en(void) } -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- + diff --git a/src/arch/pic32/tn_arch_pic32.h b/src/arch/pic32/tn_arch_pic32.h index ac7bd9c..5155e90 100644 --- a/src/arch/pic32/tn_arch_pic32.h +++ b/src/arch/pic32/tn_arch_pic32.h @@ -45,15 +45,46 @@ #ifndef _TN_ARCH_PIC32_H #define _TN_ARCH_PIC32_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + //-- this include is needed to get build-time configuration // (TN_DEBUG is used) #include "../../core/tn_common.h" + + #ifdef __cplusplus extern "C" { /*}*/ #endif + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +/// current interrupt nesting count. Used by macros +/// `tn_soft_isr()` and `tn_srs_isr()`. +extern volatile int tn_p32_int_nest_count; + +/// saved task stack pointer. Needed when switching stack pointer from +/// task stack to interrupt stack. +extern void *tn_p32_user_sp; + +/// saved ISR stack pointer. Needed when switching stack pointer from +/// interrupt stack to task stack. +extern void *tn_p32_int_sp; + + + + + + + + #ifndef DOXYGEN_SHOULD_SKIP_THIS #define _TN_PIC32_INTSAVE_DATA_INVALID 0xffffffff @@ -303,18 +334,18 @@ void __attribute__((naked, nomips16)) \ asm volatile("rdpgpr $sp, $sp"); \ \ /* Increase interrupt nesting count */ \ - asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ - asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \ + asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("addiu $k1, $k1, 1"); \ - asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("ori $k0, $zero, 1"); \ asm volatile("bne $k1, $k0, 1f"); \ \ /* Swap stack pointers if nesting count is one */ \ - asm volatile("lui $k0, %hi(tn_user_sp)"); \ - asm volatile("sw $sp, %lo(tn_user_sp)($k0)"); \ - asm volatile("lui $k0, %hi(tn_int_sp)"); \ - asm volatile("lw $sp, %lo(tn_int_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \ + asm volatile("sw $sp, %lo(tn_p32_user_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \ + asm volatile("lw $sp, %lo(tn_p32_int_sp)($k0)"); \ \ asm volatile("1:"); \ /* Save context on stack */ \ @@ -396,18 +427,18 @@ void __attribute__((naked, nomips16)) \ asm volatile("addiu $sp, $sp, 92"); \ \ /* Decrease interrupt nesting count */ \ - asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ - asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \ + asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("addiu $k1, $k1, -1"); \ - asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("bne $k1, $zero, 1f"); \ asm volatile("lw $k1, -4($sp)"); \ \ /* Swap stack pointers if nesting count is zero */ \ - asm volatile("lui $k0, %hi(tn_int_sp)"); \ - asm volatile("sw $sp, %lo(tn_int_sp)($k0)"); \ - asm volatile("lui $k0, %hi(tn_user_sp)"); \ - asm volatile("lw $sp, %lo(tn_user_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \ + asm volatile("sw $sp, %lo(tn_p32_int_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \ + asm volatile("lw $sp, %lo(tn_p32_user_sp)($k0)"); \ \ asm volatile("1:"); \ asm volatile("wrpgpr $sp, $sp"); \ @@ -452,18 +483,18 @@ void __attribute__((naked, nomips16)) \ asm volatile("rdpgpr $sp, $sp"); \ \ /* Increase interrupt nesting count */ \ - asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ - asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \ + asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("addiu $k1, $k1, 1"); \ - asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("ori $k0, $zero, 1"); \ asm volatile("bne $k1, $k0, 1f"); \ \ /* Swap stack pointers if nesting count is one */ \ - asm volatile("lui $k0, %hi(tn_user_sp)"); \ - asm volatile("sw $sp, %lo(tn_user_sp)($k0)"); \ - asm volatile("lui $k0, %hi(tn_int_sp)"); \ - asm volatile("lw $sp, %lo(tn_int_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \ + asm volatile("sw $sp, %lo(tn_p32_user_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \ + asm volatile("lw $sp, %lo(tn_p32_int_sp)($k0)"); \ \ asm volatile("1:"); \ /* Save context on stack */ \ @@ -509,18 +540,18 @@ void __attribute__((naked, nomips16)) \ asm volatile("addiu $sp, $sp, 20"); \ \ /* Decrease interrupt nesting count */ \ - asm volatile("lui $k0, %hi(tn_int_nest_count)"); \ - asm volatile("lw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \ + asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("addiu $k1, $k1, -1"); \ - asm volatile("sw $k1, %lo(tn_int_nest_count)($k0)"); \ + asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \ asm volatile("bne $k1, $zero, 1f"); \ asm volatile("lw $k1, -4($sp)"); \ \ /* Swap stack pointers if nesting count is zero */ \ - asm volatile("lui $k0, %hi(tn_int_sp)"); \ - asm volatile("sw $sp, %lo(tn_int_sp)($k0)"); \ - asm volatile("lui $k0, %hi(tn_user_sp)"); \ - asm volatile("lw $sp, %lo(tn_user_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \ + asm volatile("sw $sp, %lo(tn_p32_int_sp)($k0)"); \ + asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \ + asm volatile("lw $sp, %lo(tn_p32_user_sp)($k0)"); \ \ asm volatile("1:"); \ asm volatile("wrpgpr $sp, $sp"); \ diff --git a/src/arch/tn_arch.h b/src/arch/tn_arch.h index 8cbb050..f62b5c2 100644 --- a/src/arch/tn_arch.h +++ b/src/arch/tn_arch.h @@ -103,7 +103,13 @@ TN_UWord tn_arch_sr_save_int_dis(void); */ void tn_arch_sr_restore(TN_UWord sr); - +/* + * Architecture-dependent system startup routine. + */ +void _tn_arch_sys_init( + TN_UWord *int_stack, + unsigned int int_stack_size + ); /** diff --git a/src/core/internal/_tn_sys.h b/src/core/internal/_tn_sys.h index d814a0f..0b0b54f 100644 --- a/src/core/internal/_tn_sys.h +++ b/src/core/internal/_tn_sys.h @@ -88,18 +88,6 @@ extern volatile unsigned int tn_ready_to_run_bmp; /// by tn_timer.h subsystem. extern volatile unsigned int tn_sys_time_count; -/// current interrupt nesting count. Used by macros -/// `tn_soft_isr()` and `tn_srs_isr()`. -extern volatile int tn_int_nest_count; - -/// saved task stack pointer. Needed when switching stack pointer from -/// task stack to interrupt stack. -extern void *tn_user_sp; - -/// saved ISR stack pointer. Needed when switching stack pointer from -/// interrupt stack to task stack. -extern void *tn_int_sp; - /// /// idle task structure extern struct TN_Task tn_idle_task; diff --git a/src/core/tn_sys.c b/src/core/tn_sys.c index 255222e..112923a 100644 --- a/src/core/tn_sys.c +++ b/src/core/tn_sys.c @@ -84,15 +84,11 @@ volatile unsigned int tn_ready_to_run_bmp; volatile unsigned int tn_sys_time_count; -volatile int tn_int_nest_count; #if TN_MUTEX_DEADLOCK_DETECT volatile int tn_deadlocks_cnt = 0; #endif -void *tn_user_sp; -void *tn_int_sp; - //-- System tasks //-- idle task - priority (TN_PRIORITIES_CNT - 1) - lowest @@ -208,6 +204,9 @@ void tn_sys_start( int i; enum TN_RCode rc; + //-- call architecture-dependent initialization + _tn_arch_sys_init(int_stack, int_stack_size); + //-- for each priority: // - reset list of runnable tasks with this priority // - reset time slice to `#TN_NO_TIME_SLICE` @@ -229,9 +228,6 @@ void tn_sys_start( //-- reset system time tn_sys_time_count = 0; - //-- reset interrupt nesting count - tn_int_nest_count = 0; - //-- reset pointers to currently running task and next task to run tn_next_task_to_run = TN_NULL; tn_curr_run_task = TN_NULL; @@ -244,12 +240,6 @@ void tn_sys_start( int_stack[i] = TN_FILL_STACK_VAL; } - //-- set interrupt's top of the stack - tn_int_sp = _tn_arch_stack_top_get( - int_stack, - int_stack_size - ); - //-- init timers _tn_timers_init(); From 0b116f0a80142c5c37186dbc9af4bec8f3613765 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Wed, 29 Oct 2014 04:39:50 +0300 Subject: [PATCH 35/96] pic24: separate interrupt stack works --- src/arch/pic24_dspic/tn_arch_pic24.S | 26 ++++++-- src/arch/pic24_dspic/tn_arch_pic24.h | 88 +++++++++++++++----------- src/arch/pic24_dspic/tn_arch_pic24_c.c | 14 ++++ 3 files changed, 86 insertions(+), 42 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 69d2311..d9dbffa 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -48,6 +48,7 @@ .global __tn_arch_context_switch_now_nosave .global __tn_arch_context_switch_pend .global __tn_arch_is_int_disabled + .global __tn_arch_inside_isr .global _tn_arch_sr_save_int_dis .global _tn_arch_sr_restore .global __INT0Interrupt @@ -67,8 +68,7 @@ __tn_arch_context_switch_now_nosave: /* ---- */ - mov #_tn_next_task_to_run, W1 ; W1 = &tn_next_task_to_run - mov [W1], W1 ; W1 = tn_next_task_to_run + mov _tn_next_task_to_run, W1 ; W1 = tn_next_task_to_run mov #_tn_curr_run_task, W0 ; W0 = &tn_curr_run_task mov W1, [W0] ; tn_curr_run_task = tn_next_task_to_run @@ -119,8 +119,7 @@ __INT0Interrupt: /* store sp in preemted task's TCB */ - mov #_tn_curr_run_task, W0 ; move current task stack pointer to W0 - mov [W0], W0 + mov _tn_curr_run_task, W0 ; move current task stack pointer to W0 mov W15, [W0] /* save SR in W2 */ @@ -138,8 +137,7 @@ __INT0Interrupt: /* tn_curr_run_task = tn_next_task_to_run */ - mov #_tn_next_task_to_run, W1 ; W1 = &tn_next_task_to_run - mov [W1], W1 ; W1 = tn_next_task_to_run + mov _tn_next_task_to_run, W1 ; W1 = tn_next_task_to_run mov #_tn_curr_run_task, W0 ; W0 = &tn_curr_run_task mov W1, [W0] ; tn_curr_run_task = tn_next_task_to_run @@ -241,6 +239,22 @@ __tn_arch_is_int_disabled: 2: return + + + +__tn_arch_inside_isr: + + //-- here, we check if SPLIM is equal to __tn_p24_int_splim. + // If it is, we are inside ISR. + + mov __tn_p24_int_splim, w0 + cp SPLIM + mov #0, W0 + bra nz, 1f + mov #1, W0 +1: + return + /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 6c010cb..8918efc 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -250,61 +250,77 @@ typedef unsigned int TN_UWord; -#endif //-- DOXYGEN_SHOULD_SKIP_THIS - - +#define _tn_soft_isr_prologue \ + " \n" \ +" push w0; \n" \ +" push w1; \n" \ +\ +" mov __tn_p24_int_splim, w0; \n" \ +" cp SPLIM; \n" \ +" bra z, 1f; \n" \ +" \n" \ +" mov SPLIM, w1; \n" \ +" mov w0, SPLIM; \n" \ +" mov w15, w0; \n" \ +" mov __tn_p24_int_stack_low_addr, w15; \n" \ +" push w0; \n" /*push SP*/\ +" push w1; \n" /*push SPLIM*/\ +" bra 2f; \n" \ +"1: \n" \ +" push w15; \n" /*push SP*/\ +" push SPLIM; \n" /*push SPLIM*/\ +"2: \n" \ +" \n" \ + + +#define _tn_soft_isr_call \ + " rcall 1f; \n" + +#define _tn_soft_isr_epilogue \ + " pop w1; \n" /*pop SPLIM*/\ + " pop w0; \n" /*pop SP*/\ + " mov w1, SPLIM; \n" \ + " mov w0, w15; \n" \ + " pop w1; \n" \ + " pop w0; \n" \ + " retfie; \n" \ + "1: mov SR, w0; \n" \ + " mov.b w0, [w15-1]; " +#endif //-- DOXYGEN_SHOULD_SKIP_THIS -// --------------------------------------------------------------------------- -extern volatile unsigned int __tn_p24_dspic_inside_isr; - #define _avixInternalISR_Prologue \ -" push w0; \n" \ -" push w1; \n" \ -" push w15; \n" \ -" mov #__tn_p24_dspic_inside_isr, w0; \n" \ -" mov #1, w1; \n" \ -" mov w1, [w0]; \n" \ - #define _avixInternalISR_Activate \ - " rcall 1f; \n" - #define _avixInternalISR_Epilogue \ -" mov #__tn_p24_dspic_inside_isr, w0; \n" \ -" mov #0, w1; \n" \ -" mov w1, [w0]; \n" \ -" pop w15; \n" \ -" pop w1; \n" \ -" pop w0; \n" \ -" retfie; \n" \ -"1: mov SR, w0; \n" \ -" mov.b w0, [w15-1]; " +// --------------------------------------------------------------------------- - #define _avixDeclareISRInternalUse(f,p,s) \ - \ - void __attribute__((__interrupt__ \ - ( \ - __preprologue__ \ - ( _avixInternalISR_Prologue \ - _avixInternalISR_Activate \ - _avixInternalISR_Epilogue \ - ) \ - ), \ - p, s)) f(void) +#define _tn_soft_isr_internal(_func, _psv, _shadow) \ + void __attribute__(( \ + __interrupt__(\ + __preprologue__( \ + _tn_soft_isr_prologue \ + _tn_soft_isr_call \ + _tn_soft_isr_epilogue \ + ) \ + ), \ + _psv,\ + _shadow \ + )) \ + _func(void) -#define tn_soft_isr(f,p) _avixDeclareISRInternalUse(f,p,) +#define tn_soft_isr(_func, _psv) _tn_soft_isr_internal(_func, _psv,) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 407a498..5880d5d 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -38,8 +38,20 @@ volatile unsigned int _tn_p24_dspic_inside_isr = 0; +TN_UWord *_tn_p24_int_stack_low_addr = TN_NULL; +TN_UWord *_tn_p24_int_splim = TN_NULL; + +void _tn_arch_sys_init( + TN_UWord *int_stack, + unsigned int int_stack_size + ) +{ + _tn_p24_int_stack_low_addr = int_stack; + _tn_p24_int_splim = int_stack + int_stack_size - 1 - 1; +} + TN_UWord *_tn_arch_stack_top_get( TN_UWord *stack_low_address, int stack_size @@ -97,10 +109,12 @@ void tn_arch_int_en(void) //TODO } +#if 0 int _tn_arch_inside_isr(void) { return _tn_p24_dspic_inside_isr; } +#endif //---------------------------------------------------------------------------- From 2419ab505c49d76321619bb2322239969f3174bc Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Wed, 29 Oct 2014 04:44:19 +0300 Subject: [PATCH 36/96] little cleanup --- src/arch/pic24_dspic/tn_arch_pic24.S | 1 - src/arch/pic24_dspic/tn_arch_pic24_c.c | 12 +++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index d9dbffa..58dea42 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -41,7 +41,6 @@ .extern tn_curr_run_task .extern tn_next_task_to_run .extern IFS0 - .extern _tn_p24_dspic_inside_isr /* Public functions declared in this file */ diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 5880d5d..b9ce764 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -36,10 +36,9 @@ #include "tn_tasks.h" -volatile unsigned int _tn_p24_dspic_inside_isr = 0; TN_UWord *_tn_p24_int_stack_low_addr = TN_NULL; -TN_UWord *_tn_p24_int_splim = TN_NULL; +TN_UWord *_tn_p24_int_splim = TN_NULL; @@ -52,6 +51,7 @@ void _tn_arch_sys_init( _tn_p24_int_splim = int_stack + int_stack_size - 1 - 1; } + TN_UWord *_tn_arch_stack_top_get( TN_UWord *stack_low_address, int stack_size @@ -60,6 +60,7 @@ TN_UWord *_tn_arch_stack_top_get( return stack_low_address; } + TN_UWord *_tn_arch_stack_init( TN_TaskBody *task_func, TN_UWord *stack_top, @@ -109,13 +110,6 @@ void tn_arch_int_en(void) //TODO } -#if 0 -int _tn_arch_inside_isr(void) -{ - return _tn_p24_dspic_inside_isr; -} -#endif - //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- From 08ee4bb3a38461360582b6ee8f4f8dbb197048fe Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Thu, 30 Oct 2014 11:41:12 +0300 Subject: [PATCH 37/96] pic24: the kernel now disables only interrupts with priority [1..4], so that system services are allowed to call only from interrupts with priorities in this range --- src/arch/pic24_dspic/tn_arch_pic24.S | 18 ++++++------ src/arch/pic24_dspic/tn_arch_pic24.h | 41 +++++++++++++++------------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 58dea42..604661c 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -34,6 +34,9 @@ * ******************************************************************************/ +#define TN_IPL #0x80 +#define TN_IPL_SHIFTED #0x04 + .text /* External references */ @@ -131,7 +134,8 @@ __INT0Interrupt: /* disable interrupts */ mov _SR, W0 - xor #0xE0, W0 + xor TN_IPL, W0 + and #0xE0, W0 xor _SR /* tn_curr_run_task = tn_next_task_to_run */ @@ -185,12 +189,9 @@ _tn_arch_sr_save_int_dis: push _SR - ;mov _SR, W0 - ;ior #0xE0, W0 - ;mov W0, _SR - mov _SR, W0 - xor #0xE0, W0 + xor TN_IPL, W0 + and #0xE0, W0 xor _SR pop W0 @@ -224,13 +225,12 @@ _tn_arch_sr_restore: *----------------------------------------------------------------------------*/ __tn_arch_is_int_disabled: - /* TODO: optimize */ mov #0xE0, W0 and _SR, WREG lsr W0, #5, W0 - cp W0, #0x7 - bra Z, 1f + cp W0, TN_IPL_SHIFTED + bra geu, 1f mov #0, W0 bra 2f 1: diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 8918efc..3953607 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -252,25 +252,28 @@ typedef unsigned int TN_UWord; #define _tn_soft_isr_prologue \ " \n" \ -" push w0; \n" \ -" push w1; \n" \ -\ -" mov __tn_p24_int_splim, w0; \n" \ -" cp SPLIM; \n" \ -" bra z, 1f; \n" \ -" \n" \ -" mov SPLIM, w1; \n" \ -" mov w0, SPLIM; \n" \ -" mov w15, w0; \n" \ -" mov __tn_p24_int_stack_low_addr, w15; \n" \ -" push w0; \n" /*push SP*/\ -" push w1; \n" /*push SPLIM*/\ -" bra 2f; \n" \ -"1: \n" \ -" push w15; \n" /*push SP*/\ -" push SPLIM; \n" /*push SPLIM*/\ -"2: \n" \ -" \n" \ + " push w0; \n" \ + " push w1; \n" \ + \ + " mov __tn_p24_int_splim, w0; \n" \ + " cp SPLIM; \n" \ + " bra z, 1f; \n" \ + " \n" \ + " mov SPLIM, w1; \n" \ + " mov w0, SPLIM; \n" \ + " mov w15, w0; \n" \ + " mov __tn_p24_int_stack_low_addr, w15; \n" \ + \ + /* now, interrupt stack is used. */\ + /* we need to push previous stack pointer and SPLIM there. */\ + " push w0; \n" /*push task's SP*/\ + " push w1; \n" /*push task's SPLIM*/\ + " bra 2f; \n" \ + "1: \n" \ + " push w15; \n" /*push SP*/\ + " push SPLIM; \n" /*push SPLIM*/\ + "2: \n" \ + " \n" \ #define _tn_soft_isr_call \ From cc0ada97c27d201bb5d3b2a1c4d13f302b56616f Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Thu, 30 Oct 2014 11:45:21 +0300 Subject: [PATCH 38/96] pic24: refactor TN_IPL a bit --- src/arch/pic24_dspic/tn_arch_pic24.S | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 604661c..43278a7 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -34,8 +34,8 @@ * ******************************************************************************/ -#define TN_IPL #0x80 -#define TN_IPL_SHIFTED #0x04 +#define TN_IPL #0x04 +#define TN_IPL_SHIFTED #(TN_IPL << 5) .text @@ -133,9 +133,9 @@ __INT0Interrupt: mov W0, _SPLIM /* disable interrupts */ - mov _SR, W0 - xor TN_IPL, W0 - and #0xE0, W0 + mov _SR, W0 + xor TN_IPL_SHIFTED, W0 + and #0xE0, W0 xor _SR /* tn_curr_run_task = tn_next_task_to_run */ @@ -189,9 +189,9 @@ _tn_arch_sr_save_int_dis: push _SR - mov _SR, W0 - xor TN_IPL, W0 - and #0xE0, W0 + mov _SR, W0 + xor TN_IPL_SHIFTED, W0 + and #0xE0, W0 xor _SR pop W0 @@ -229,7 +229,7 @@ __tn_arch_is_int_disabled: mov #0xE0, W0 and _SR, WREG lsr W0, #5, W0 - cp W0, TN_IPL_SHIFTED + cp W0, TN_IPL bra geu, 1f mov #0, W0 bra 2f From e2b28f5f64b5cc8bd88f7bf7871100754d83c0f8 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Thu, 30 Oct 2014 11:45:41 +0300 Subject: [PATCH 39/96] little typo fixed: double semicolon removed --- src/core/tn_fmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/tn_fmem.h b/src/core/tn_fmem.h index 61ef0ad..e77f8a3 100644 --- a/src/core/tn_fmem.h +++ b/src/core/tn_fmem.h @@ -238,7 +238,7 @@ enum TN_RCode tn_fmem_create( * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`. * */ -enum TN_RCode tn_fmem_delete(struct TN_FMem *fmem);; +enum TN_RCode tn_fmem_delete(struct TN_FMem *fmem); /** * Get memory block from the pool. Start address of the memory block is returned From e1c0d2a1411e1798d5bbb3353456f8febb0ea9c0 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Thu, 30 Oct 2014 19:47:20 +0300 Subject: [PATCH 40/96] pic24: tn_soft_isr() macro now optionally (if TN_CHECK_PARAM is non-zero) checks that interrupt priority is not too high --- src/arch/pic24_dspic/tn_arch_pic24.S | 14 +++++--- src/arch/pic24_dspic/tn_arch_pic24.h | 36 ++++++++++++++++++- .../nbproject/configurations.xml | 3 +- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 43278a7..cd3da06 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -34,8 +34,12 @@ * ******************************************************************************/ -#define TN_IPL #0x04 -#define TN_IPL_SHIFTED #(TN_IPL << 5) +//TODO: this symbol is now defined in two places +//(tn_arch_pic24.h, tn_arch_pic24.S) +//need to fix it +#define _TN_IPL 0x04 +#define _TN_IPL_SHIFTED (_TN_IPL << 5) + .text @@ -134,7 +138,7 @@ __INT0Interrupt: /* disable interrupts */ mov _SR, W0 - xor TN_IPL_SHIFTED, W0 + xor #_TN_IPL_SHIFTED, W0 and #0xE0, W0 xor _SR @@ -190,7 +194,7 @@ _tn_arch_sr_save_int_dis: push _SR mov _SR, W0 - xor TN_IPL_SHIFTED, W0 + xor #_TN_IPL_SHIFTED, W0 and #0xE0, W0 xor _SR @@ -229,7 +233,7 @@ __tn_arch_is_int_disabled: mov #0xE0, W0 and _SR, WREG lsr W0, #5, W0 - cp W0, TN_IPL + cp W0, #_TN_IPL bra geu, 1f mov #0, W0 bra 2f diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 3953607..00c9e81 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -248,13 +248,47 @@ typedef unsigned int TN_UWord; */ #define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 1) +//TODO: this symbol is now defined in two places +//(tn_arch_pic24.h, tn_arch_pic24.S) +//need to fix it +#define _TN_IPL "0x04" + + + +#if TN_CHECK_PARAM + +/** + * Check whether priority is too high. On PIC24 port, we have a range of + * interrupt priorities (let's call this range as "system priority"), and + * kernel functions are allowed to call only from ISRs with priority in this + * range. + * + * As a result, the kernel never disables ALL interrupts: when it modifies + * critical data, it disables just interrupts with system priority. + */ +# define _tn_soft_isr_priority_check \ + " \n" \ + " mov #0xE0, W0 \n" \ + " and _SR, WREG \n" \ + " lsr W0, #5, W0 \n" \ + " cp W0, #" _TN_IPL " \n" \ + " bra leu, 1f \n" \ + " .pword 0xDA4000 \n" \ + " nop \n" \ + "1: \n" \ + +#else +# define _tn_soft_isr_priority_check /* nothing */ +#endif #define _tn_soft_isr_prologue \ " \n" \ " push w0; \n" \ " push w1; \n" \ - \ +\ +_tn_soft_isr_priority_check\ +\ " mov __tn_p24_int_splim, w0; \n" \ " cp SPLIM; \n" \ " bra z, 1f; \n" \ diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml index 75513fb..55162b1 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml @@ -119,7 +119,8 @@ - + From 7088ad3cca464bda8c5398aaa37be12dd38c682b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Thu, 30 Oct 2014 19:50:58 +0300 Subject: [PATCH 41/96] pic24: interrupts are disabled for 4 cycles when it modifies SP and SPLIM --- src/arch/pic24_dspic/tn_arch_pic24.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 00c9e81..4fd0c3b 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -263,8 +263,14 @@ typedef unsigned int TN_UWord; * kernel functions are allowed to call only from ISRs with priority in this * range. * - * As a result, the kernel never disables ALL interrupts: when it modifies - * critical data, it disables just interrupts with system priority. + * As a result, the kernel (almost) never disables ALL interrupts: when it + * modifies critical data, it disables just interrupts with system priority. + * + * The "almost" is because it disables interrupts for 4 cycles when it modifies + * stack pointer and SPLIM, because they should always correspond. We could + * avoid even this by first setting SPLIM to 0xffff, then modifying SP, and + * then setting SPLIM to new correct value, this would take additional register + * to save, and this would work longer, so I decided to just 'disi #4'. */ # define _tn_soft_isr_priority_check \ " \n" \ @@ -293,6 +299,7 @@ _tn_soft_isr_priority_check\ " cp SPLIM; \n" \ " bra z, 1f; \n" \ " \n" \ + " disi #4; \n" \ " mov SPLIM, w1; \n" \ " mov w0, SPLIM; \n" \ " mov w15, w0; \n" \ @@ -314,6 +321,7 @@ _tn_soft_isr_priority_check\ " rcall 1f; \n" #define _tn_soft_isr_epilogue \ + " disi #4; \n" \ " pop w1; \n" /*pop SPLIM*/\ " pop w0; \n" /*pop SP*/\ " mov w1, SPLIM; \n" \ From 1d8e6ab94fe47c1c0008c76c85072d163d35444b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 31 Oct 2014 08:29:05 +0300 Subject: [PATCH 42/96] docs fixed a bit --- stuff/doc_pages/tnkernel_diff.dox | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stuff/doc_pages/tnkernel_diff.dox b/stuff/doc_pages/tnkernel_diff.dox index 186d6b4..8f57c63 100644 --- a/stuff/doc_pages/tnkernel_diff.dox +++ b/stuff/doc_pages/tnkernel_diff.dox @@ -122,7 +122,9 @@ Meanwhile, attributes like `TN_EVENT_ATTR_SINGLE`, `TN_EVENT_ATTR_CLR` imply tha After all, when we call `tn_event_clear(&my_event_obj, flags)`, we might expect that `flags` argument actually specifies flags to clear. But in fact, we must invert it, to make it work: `~flags`. This is really confusing. -In TNeoKernel, there is no such *event* object. Instead, there is object *events group*. Attributes like `...SINGLE`, `...MULTI`, `...CLR` are removed, since they make no sense for events group. I have plans to offer a way to *connect* events group to queue and probably other kernel objects as well, so that queue will set and clear particular flag in the events group automatically, depending on whether a queue is empty. By means of that, it is quite easy to wait for data from multiple queues with just a single call to `tn_eventgrp_wait()`. +In TNeoKernel, there is no such *event* object. Instead, there is object *events group*. Attributes like `...SINGLE`, `...MULTI`, `...CLR` are removed, since they make no sense for events group. + +TNeoKernel also offers a very useful feature: connecting an event group to other kernel objects. Read \ref tnkernel_new_features__eventgrp_conn "below". For detailed API reference, refer to the `tn_eventgrp.h`. From b12160342ae6db9dd0704e86470196655fa60052 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 31 Oct 2014 12:45:51 +0300 Subject: [PATCH 43/96] pic24: added comments for isr wrapper macro --- src/arch/pic24_dspic/tn_arch_pic24.h | 46 +++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 4fd0c3b..bf26c36 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -266,7 +266,7 @@ typedef unsigned int TN_UWord; * As a result, the kernel (almost) never disables ALL interrupts: when it * modifies critical data, it disables just interrupts with system priority. * - * The "almost" is because it disables interrupts for 4 cycles when it modifies + * The "almost" is because it disables interrupts for 4-8 cycles when it modifies * stack pointer and SPLIM, because they should always correspond. We could * avoid even this by first setting SPLIM to 0xffff, then modifying SP, and * then setting SPLIM to new correct value, this would take additional register @@ -290,47 +290,77 @@ typedef unsigned int TN_UWord; #define _tn_soft_isr_prologue \ " \n" \ + /* we need to use a couple of registers, so, save them. */\ " push w0; \n" \ " push w1; \n" \ \ +/* if TN_CHECK_PARAM is enabled, check if interrupt priority is too high. */\ +/* See macro _tn_soft_isr_priority_check above for details. */\ _tn_soft_isr_priority_check\ \ +/* before playing with SP and SPLIM, we need to disable system interrupts */\ +/* NOTE that 'disi' instruction does not disable interrupts with priority 7, */\ +/* so, system interrupt priority should never be 7. */\ + " disi #8; \n" \ +/* check if SP is already inside the interrupt stack: */ \ +/* we check it by checking if SPLIM is set to _tn_p24_int_splim */ \ " mov __tn_p24_int_splim, w0; \n" \ " cp SPLIM; \n" \ " bra z, 1f; \n" \ +\ +/* SP is not inside the interrupt stack. We should set it. */\ " \n" \ - " disi #4; \n" \ " mov SPLIM, w1; \n" \ " mov w0, SPLIM; \n" \ " mov w15, w0; \n" \ " mov __tn_p24_int_stack_low_addr, w15; \n" \ \ - /* now, interrupt stack is used. */\ + /* Interrupts should be re-enabled here. */\ + /* We just switched to interrupt stack. */\ /* we need to push previous stack pointer and SPLIM there. */\ " push w0; \n" /*push task's SP*/\ " push w1; \n" /*push task's SPLIM*/\ " bra 2f; \n" \ "1: \n" \ +/* Interrupt stack is already active (it happens when interrupts nest) */\ +/* Just push SP and SPLIM so that stack will be compatible with the case of */\ +/* non-nested interrupt */\ " push w15; \n" /*push SP*/\ " push SPLIM; \n" /*push SPLIM*/\ "2: \n" \ " \n" \ - #define _tn_soft_isr_call \ + /* before we call user-provided ISR, we need to imitate interrupt call, */\ + /* i.e. store SR to the stack. It is done below, at the label 1: */\ " rcall 1f; \n" #define _tn_soft_isr_epilogue \ + /* we got here when we just returned from user-provided ISR. */\ + /* now, we need to restore previous SPLIM and SP, and we should disable */\ + /* interrupts because they could nest, and if SPLIM and SP don't */\ + /* correspond, system crashes. */\ " disi #4; \n" \ - " pop w1; \n" /*pop SPLIM*/\ - " pop w0; \n" /*pop SP*/\ + " pop w1; \n" /*pop SPLIM*/\ + " pop w0; \n" /*pop SP*/\ " mov w1, SPLIM; \n" \ " mov w0, w15; \n" \ + /* now, interrupts should be enabled back. */\ + /* here we just need to restore w0 and w1 that we saved and used in */\ + /* _tn_soft_isr_prologue */\ " pop w1; \n" \ " pop w0; \n" \ + /* finally, return from the ISR. */\ " retfie; \n" \ - "1: mov SR, w0; \n" \ - " mov.b w0, [w15-1]; " + "1: \n" \ + /* we got here by rcall when we are about to call user-provided ISR. */\ + /* 'rcall' saves program counter to the stack, but we need to imitate */\ + /* interrupt, so, we manually save SR there. */\ + " mov SR, w0; \n" \ + " mov.b w0, [w15-1]; " \ + /* now, we eventually proceed to user-provided ISR. */\ + /* When it returns, we get above to the macro _tn_soft_isr_prologue */\ + /* (because 'rcall' saved this address to the stack) */\ From d67e2ab04d40e56678686e5fa506dc5caea13a8e Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 31 Oct 2014 14:19:14 +0300 Subject: [PATCH 44/96] pic24: isr wrapper macros cleaned up --- src/arch/pic24_dspic/tn_arch_pic24.h | 213 ++++++++++++++------------- 1 file changed, 110 insertions(+), 103 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index bf26c36..aaad1c3 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -267,102 +267,109 @@ typedef unsigned int TN_UWord; * modifies critical data, it disables just interrupts with system priority. * * The "almost" is because it disables interrupts for 4-8 cycles when it modifies - * stack pointer and SPLIM, because they should always correspond. We could - * avoid even this by first setting SPLIM to 0xffff, then modifying SP, and - * then setting SPLIM to new correct value, this would take additional register - * to save, and this would work longer, so I decided to just 'disi #4'. + * stack pointer and SPLIM, because they should always correspond. */ -# define _tn_soft_isr_priority_check \ - " \n" \ - " mov #0xE0, W0 \n" \ - " and _SR, WREG \n" \ - " lsr W0, #5, W0 \n" \ - " cp W0, #" _TN_IPL " \n" \ - " bra leu, 1f \n" \ - " .pword 0xDA4000 \n" \ - " nop \n" \ - "1: \n" \ +# define _TN_SOFT_ISR_PRIORITY_CHECK() \ + " \n" \ + " mov #0xE0, W0 \n" \ + " and _SR, WREG \n" \ + " lsr W0, #5, W0 \n" \ + " cp W0, #" _TN_IPL " \n" \ + " bra leu, 1f \n" \ + " .pword 0xDA4000 \n" \ + " nop \n" \ + "1: \n" \ #else -# define _tn_soft_isr_priority_check /* nothing */ +# define _TN_SOFT_ISR_PRIORITY_CHECK() /* nothing */ #endif -#define _tn_soft_isr_prologue \ - " \n" \ - /* we need to use a couple of registers, so, save them. */\ - " push w0; \n" \ - " push w1; \n" \ -\ -/* if TN_CHECK_PARAM is enabled, check if interrupt priority is too high. */\ -/* See macro _tn_soft_isr_priority_check above for details. */\ -_tn_soft_isr_priority_check\ -\ -/* before playing with SP and SPLIM, we need to disable system interrupts */\ -/* NOTE that 'disi' instruction does not disable interrupts with priority 7, */\ -/* so, system interrupt priority should never be 7. */\ - " disi #8; \n" \ -/* check if SP is already inside the interrupt stack: */ \ -/* we check it by checking if SPLIM is set to _tn_p24_int_splim */ \ - " mov __tn_p24_int_splim, w0; \n" \ - " cp SPLIM; \n" \ - " bra z, 1f; \n" \ -\ -/* SP is not inside the interrupt stack. We should set it. */\ - " \n" \ - " mov SPLIM, w1; \n" \ - " mov w0, SPLIM; \n" \ - " mov w15, w0; \n" \ - " mov __tn_p24_int_stack_low_addr, w15; \n" \ - \ - /* Interrupts should be re-enabled here. */\ - /* We just switched to interrupt stack. */\ - /* we need to push previous stack pointer and SPLIM there. */\ - " push w0; \n" /*push task's SP*/\ - " push w1; \n" /*push task's SPLIM*/\ - " bra 2f; \n" \ - "1: \n" \ -/* Interrupt stack is already active (it happens when interrupts nest) */\ -/* Just push SP and SPLIM so that stack will be compatible with the case of */\ -/* non-nested interrupt */\ - " push w15; \n" /*push SP*/\ - " push SPLIM; \n" /*push SPLIM*/\ - "2: \n" \ - " \n" \ - -#define _tn_soft_isr_call \ - /* before we call user-provided ISR, we need to imitate interrupt call, */\ - /* i.e. store SR to the stack. It is done below, at the label 1: */\ - " rcall 1f; \n" - -#define _tn_soft_isr_epilogue \ - /* we got here when we just returned from user-provided ISR. */\ - /* now, we need to restore previous SPLIM and SP, and we should disable */\ - /* interrupts because they could nest, and if SPLIM and SP don't */\ - /* correspond, system crashes. */\ - " disi #4; \n" \ - " pop w1; \n" /*pop SPLIM*/\ - " pop w0; \n" /*pop SP*/\ - " mov w1, SPLIM; \n" \ - " mov w0, w15; \n" \ - /* now, interrupts should be enabled back. */\ - /* here we just need to restore w0 and w1 that we saved and used in */\ - /* _tn_soft_isr_prologue */\ - " pop w1; \n" \ - " pop w0; \n" \ - /* finally, return from the ISR. */\ - " retfie; \n" \ - "1: \n" \ - /* we got here by rcall when we are about to call user-provided ISR. */\ - /* 'rcall' saves program counter to the stack, but we need to imitate */\ - /* interrupt, so, we manually save SR there. */\ - " mov SR, w0; \n" \ - " mov.b w0, [w15-1]; " \ - /* now, we eventually proceed to user-provided ISR. */\ - /* When it returns, we get above to the macro _tn_soft_isr_prologue */\ - /* (because 'rcall' saved this address to the stack) */\ - - +#define _TN_SOFT_ISR_PROLOGUE \ + " \n" \ + \ + /* we need to use a couple of registers, so, save them. */ \ + " push w0; \n" \ + " push w1; \n" \ + \ + /* if TN_CHECK_PARAM is enabled, check if interrupt priority is */ \ + /* too high. See macro _TN_SOFT_ISR_PRIORITY_CHECK() above for */ \ + /* details. */ \ + _TN_SOFT_ISR_PRIORITY_CHECK() \ + \ + /* before playing with SP and SPLIM, we need to disable system */ \ + /* interrupts. NOTE that 'disi' instruction does not disable */ \ + /* interrupts with priority 7, so, system interrupt priority should */ \ + /* never be 7. */ \ + \ + " disi #8; \n" \ + \ + /* check if SP is already inside the interrupt stack: */ \ + /* we check it by checking if SPLIM is set to _tn_p24_int_splim */ \ + " mov __tn_p24_int_splim, w0; \n" \ + " cp SPLIM; \n" \ + " bra z, 1f; \n" \ + \ + /* SP is not inside the interrupt stack. We should set it. */ \ + " \n" \ + " mov SPLIM, w1; \n" \ + " mov w0, SPLIM; \n" \ + " mov w15, w0; \n" \ + " mov __tn_p24_int_stack_low_addr, w15; \n" \ + \ + /* Interrupts should be re-enabled here. */ \ + /* We just switched to interrupt stack. */ \ + /* we need to push previous stack pointer and SPLIM there. */ \ + " push w0; \n" /* push task's SP */ \ + " push w1; \n" /* push task's SPLIM */ \ + " bra 2f; \n" \ + "1: \n" \ + /* Interrupt stack is already active (it happens when interrupts */ \ + /* nest) */ \ + /* Just push SP and SPLIM so that stack will be compatible with the */ \ + /* case of non-nested interrupt */ \ + " push w15; \n" /* push SP */ \ + " push SPLIM; \n" /* push SPLIM */ \ + "2: \n" \ + " \n" \ + + +#define _TN_SOFT_ISR_CALL \ + /* before we call user-provided ISR, we need to imitate interrupt */ \ + /* call, i.e. store SR to the stack. It is done below, */ \ + /* at the label 1: */ \ + " rcall 1f; \n" + +#define _TN_SOFT_ISR_EPILOGUE \ + /* we got here when we just returned from user-provided ISR. */ \ + /* now, we need to restore previous SPLIM and SP, and we should */ \ + /* disable interrupts because they could nest, and if SPLIM and SP */ \ + /* don't */ \ + /* correspond, system crashes. */ \ + " disi #4; \n" \ + " pop w1; \n" /* pop SPLIM */ \ + " pop w0; \n" /* pop SP */ \ + " mov w1, SPLIM; \n" \ + " mov w0, w15; \n" \ + \ + /* now, interrupts should be enabled back. */ \ + /* here we just need to restore w0 and w1 that we saved and used in */ \ + /* _TN_SOFT_ISR_PROLOGUE */ \ + " pop w1; \n" \ + " pop w0; \n" \ + \ + /* finally, return from the ISR. */ \ + " retfie; \n" \ + "1: \n" \ + /* we got here by rcall when we are about to call user-provided ISR. */ \ + /* 'rcall' saves program counter to the stack, but we need to */ \ + /* imitate interrupt, so, we manually save SR there. */ \ + " mov SR, w0; \n" \ + " mov.b w0, [w15-1]; \n" \ + \ + /* now, we eventually proceed to user-provided ISR. */ \ + /* When it returns, we get above to the macro _TN_SOFT_ISR_PROLOGUE */ \ + /* (because 'rcall' saved this address to the stack) */ \ #endif //-- DOXYGEN_SHOULD_SKIP_THIS @@ -378,24 +385,24 @@ _tn_soft_isr_priority_check\ // --------------------------------------------------------------------------- -#define _tn_soft_isr_internal(_func, _psv, _shadow) \ - void __attribute__(( \ - __interrupt__(\ - __preprologue__( \ - _tn_soft_isr_prologue \ - _tn_soft_isr_call \ - _tn_soft_isr_epilogue \ - ) \ - ), \ - _psv,\ - _shadow \ - )) \ +#define _tn_soft_isr_internal(_func, _psv, _shadow) \ + void __attribute__(( \ + __interrupt__( \ + __preprologue__( \ + _TN_SOFT_ISR_PROLOGUE \ + _TN_SOFT_ISR_CALL \ + _TN_SOFT_ISR_EPILOGUE \ + ) \ + ), \ + _psv, \ + _shadow \ + )) \ _func(void) -#define tn_soft_isr(_func, _psv) _tn_soft_isr_internal(_func, _psv,) +#define tn_soft_isr(_func, _psv) _tn_soft_isr_internal(_func, _psv, ) From fe6f8e1aab8c232c8929fb324b616cd21d844bcb Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 31 Oct 2014 17:15:20 +0300 Subject: [PATCH 45/96] pic24: added user comments for tn_soft_isr() macro --- src/arch/pic24_dspic/tn_arch_pic24.h | 56 +++++++++++++++++++++------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index aaad1c3..4b093b8 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -248,13 +248,15 @@ typedef unsigned int TN_UWord; */ #define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 1) + + +//-- internal interrupt macro stuff {{{ + //TODO: this symbol is now defined in two places //(tn_arch_pic24.h, tn_arch_pic24.S) //need to fix it #define _TN_IPL "0x04" - - #if TN_CHECK_PARAM /** @@ -372,18 +374,6 @@ typedef unsigned int TN_UWord; /* (because 'rcall' saved this address to the stack) */ \ -#endif //-- DOXYGEN_SHOULD_SKIP_THIS - - - - - - - - - - -// --------------------------------------------------------------------------- #define _tn_soft_isr_internal(_func, _psv, _shadow) \ void __attribute__(( \ @@ -400,8 +390,46 @@ typedef unsigned int TN_UWord; _func(void) +// }}} + +#endif //-- DOXYGEN_SHOULD_SKIP_THIS + + + + + + + + +/** + * ISR wrapper macro for software context saving. + * + * Usage looks like the following: + * + * \code{.c} + * tn_soft_isr(_T1Interrupt, auto_psv) + * { + * //-- clear interrupt flag + * IFS0bits.T1IF = 0; + * + * //-- do something useful + * } + * \endcode + * + * Which should be used for system interrupts, instead of standard way: + * + * \code{.c} + * void __attribute__((__interrupt__, auto_psv)) _T1Interrupt(void) + * \endcode + * + * Where `_T1Interrupt` is the usual PIC24/dsPIC ISR name, + * and `auto_psv` (or `no_auto_psv`) is the usual attribute argument for + * interrupt. + * + * + */ #define tn_soft_isr(_func, _psv) _tn_soft_isr_internal(_func, _psv, ) From 774dd6945979f22425653b6f92f0c6c1ef836b86 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 31 Oct 2014 17:19:29 +0300 Subject: [PATCH 46/96] tneokernel_pic24.X -> tneokernel_pic24_dspic.X --- .../{tneokernel_pic24.X => tneokernel_pic24_dspic.X}/Makefile | 0 .../nbproject/configurations.xml | 0 .../nbproject/project.properties | 0 .../nbproject/project.xml | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename src/arch/pic24_dspic/{tneokernel_pic24.X => tneokernel_pic24_dspic.X}/Makefile (100%) rename src/arch/pic24_dspic/{tneokernel_pic24.X => tneokernel_pic24_dspic.X}/nbproject/configurations.xml (100%) rename src/arch/pic24_dspic/{tneokernel_pic24.X => tneokernel_pic24_dspic.X}/nbproject/project.properties (100%) rename src/arch/pic24_dspic/{tneokernel_pic24.X => tneokernel_pic24_dspic.X}/nbproject/project.xml (93%) diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/Makefile b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/Makefile similarity index 100% rename from src/arch/pic24_dspic/tneokernel_pic24.X/Makefile rename to src/arch/pic24_dspic/tneokernel_pic24_dspic.X/Makefile diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml similarity index 100% rename from src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/configurations.xml rename to src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.properties b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/project.properties similarity index 100% rename from src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.properties rename to src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/project.properties diff --git a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.xml b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/project.xml similarity index 93% rename from src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.xml rename to src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/project.xml index f9b4e6a..64f8895 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24.X/nbproject/project.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/project.xml @@ -2,7 +2,7 @@ com.microchip.mplab.nbide.embedded.makeproject - tneokernel_pic24 + tneokernel_pic24_dspic 455b33f3-b0bc-43d7-a5c4-84b529221aec 0 c From ee497a295bf4343edc56800fe65019ef7094c648 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 31 Oct 2014 17:34:38 +0300 Subject: [PATCH 47/96] building.dox: added info about pic24 --- stuff/doc_pages/building.dox | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stuff/doc_pages/building.dox b/stuff/doc_pages/building.dox index c57caa6..2d8e08c 100644 --- a/stuff/doc_pages/building.dox +++ b/stuff/doc_pages/building.dox @@ -38,5 +38,13 @@ it to your main project by right-clicking `Libraries -> Add Library Project ...`. Alternatively, of course you can just build it and use resulting `tneokernel.X.a` file in whatever way you like. +\section building_pic24_dspic PIC24/dsPIC port: MPLABX project + +MPLABX project resides in the `src/arch/pic24_dspic/tneokernel_pic24_dspic.X` +directory. This is a *library project* in terms of MPLABX, so if you use MPLABX +you can easily add it to your main project by right-clicking `Libraries -> Add +Library Project ...`. Alternatively, of course you can just build it and use +resulting `tneokernel_pic24_dspic.X.a` file in whatever way you like. + */ From 95614976d8d72b87aeb8a85003658859780fd9ed Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Fri, 31 Oct 2014 17:51:08 +0300 Subject: [PATCH 48/96] pic24: kernel now sets up interrupt for context switch, this is no more programmer's responsibility --- src/arch/pic24_dspic/tn_arch_pic24_c.c | 11 +++++++++++ stuff/doc_pages/changelog.dox | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index b9ce764..609a393 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -35,6 +35,7 @@ ******************************************************************************/ #include "tn_tasks.h" +#include TN_UWord *_tn_p24_int_stack_low_addr = TN_NULL; @@ -49,6 +50,16 @@ void _tn_arch_sys_init( { _tn_p24_int_stack_low_addr = int_stack; _tn_p24_int_splim = int_stack + int_stack_size - 1 - 1; + + + //-- set up software interrupt for context switching + + IPC0bits.INT0IP = 1; //-- set lowest interrupt priority + // TODO: this code isn't atomic, but this function + // is called at system startup, so, nobody should + // interfere + IFS0bits.INT0IF = 0; //-- clear interrupt flag + IEC0bits.INT0IE = 1; //-- enable interrupt } diff --git a/stuff/doc_pages/changelog.dox b/stuff/doc_pages/changelog.dox index 334a291..aa01383 100644 --- a/stuff/doc_pages/changelog.dox +++ b/stuff/doc_pages/changelog.dox @@ -7,7 +7,11 @@ TNeoKernel changelog \section changelog_current Current development version (BETA) - - *No changes yet* + - Refactor: the following symbols: `NULL`, `BOOL`, `TRUE`, `FALSE` now have + the `TN_` prefix: `#TN_NULL`, `#TN_BOOL`, `#TN_TRUE`, `#TN_FALSE`. This is + because non-prefixed symbols may be defined by some other program module, + which leads to conflicts. The easiest and robust way is to add unique + prefix. \section changelog_v1_03 v1.03 From d538748d8abcec6c590f982035ca1c09511814d1 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sat, 1 Nov 2014 15:32:43 +0300 Subject: [PATCH 49/96] pic24: a little more cleanup in ISR macro --- src/arch/pic24_dspic/tn_arch_pic24.h | 66 ++++++++++++++-------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 4b093b8..d3f5793 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -273,14 +273,17 @@ typedef unsigned int TN_UWord; */ # define _TN_SOFT_ISR_PRIORITY_CHECK() \ " \n" \ - " mov #0xE0, W0 \n" \ - " and _SR, WREG \n" \ - " lsr W0, #5, W0 \n" \ - " cp W0, #" _TN_IPL " \n" \ - " bra leu, 1f \n" \ - " .pword 0xDA4000 \n" \ + " mov #0xE0, W0 \n" \ + " and _SR, WREG \n" \ + " lsr W0, #5, W0 \n" \ + " cp W0, #" _TN_IPL " \n" \ + " bra leu, 1f \n" \ + \ + /* Interrupt priority is too high. Halt the debugger here. */ \ + " .pword 0xDA4000 \n" \ " nop \n" \ "1: \n" \ + /* Interrupt priority is ok, go on now. */ \ #else # define _TN_SOFT_ISR_PRIORITY_CHECK() /* nothing */ @@ -306,32 +309,32 @@ typedef unsigned int TN_UWord; \ " disi #8; \n" \ \ - /* check if SP is already inside the interrupt stack: */ \ - /* we check it by checking if SPLIM is set to _tn_p24_int_splim */ \ + /* check if SP is already inside the interrupt stack: */ \ + /* we check it by checking if SPLIM is set to _tn_p24_int_splim */ \ " mov __tn_p24_int_splim, w0; \n" \ " cp SPLIM; \n" \ " bra z, 1f; \n" \ \ - /* SP is not inside the interrupt stack. We should set it. */ \ + /* SP is not inside the interrupt stack. We should set it. */ \ " \n" \ - " mov SPLIM, w1; \n" \ - " mov w0, SPLIM; \n" \ - " mov w15, w0; \n" \ - " mov __tn_p24_int_stack_low_addr, w15; \n" \ + " mov SPLIM, w1; \n" \ + " mov w0, SPLIM; \n" \ + " mov w15, w0; \n" \ + " mov __tn_p24_int_stack_low_addr, w15; \n" \ \ /* Interrupts should be re-enabled here. */ \ /* We just switched to interrupt stack. */ \ /* we need to push previous stack pointer and SPLIM there. */ \ - " push w0; \n" /* push task's SP */ \ - " push w1; \n" /* push task's SPLIM */ \ - " bra 2f; \n" \ + " push w0; \n" /* push task's SP */ \ + " push w1; \n" /* push task's SPLIM */ \ + " bra 2f; \n" \ "1: \n" \ /* Interrupt stack is already active (it happens when interrupts */ \ /* nest) */ \ - /* Just push SP and SPLIM so that stack will be compatible with the */ \ - /* case of non-nested interrupt */ \ - " push w15; \n" /* push SP */ \ - " push SPLIM; \n" /* push SPLIM */ \ + /* Just push SP and SPLIM so that stack contents will be compatible */ \ + /* with the case of non-nested interrupt */ \ + " push w15; \n" /* push SP */ \ + " push SPLIM; \n" /* push SPLIM */ \ "2: \n" \ " \n" \ @@ -340,27 +343,26 @@ typedef unsigned int TN_UWord; /* before we call user-provided ISR, we need to imitate interrupt */ \ /* call, i.e. store SR to the stack. It is done below, */ \ /* at the label 1: */ \ - " rcall 1f; \n" + " rcall 1f; \n" #define _TN_SOFT_ISR_EPILOGUE \ /* we got here when we just returned from user-provided ISR. */ \ /* now, we need to restore previous SPLIM and SP, and we should */ \ /* disable interrupts because they could nest, and if SPLIM and SP */ \ - /* don't */ \ - /* correspond, system crashes. */ \ - " disi #4; \n" \ - " pop w1; \n" /* pop SPLIM */ \ - " pop w0; \n" /* pop SP */ \ - " mov w1, SPLIM; \n" \ - " mov w0, w15; \n" \ + /* don't correspond, system crashes. */ \ + " disi #4; \n" \ + " pop w1; \n" /* pop SPLIM */ \ + " pop w0; \n" /* pop SP */ \ + " mov w1, SPLIM; \n" \ + " mov w0, w15; \n" \ \ - /* now, interrupts should be enabled back. */ \ + /* now, interrupts should be enabled back. */ \ /* here we just need to restore w0 and w1 that we saved and used in */ \ - /* _TN_SOFT_ISR_PROLOGUE */ \ + /* _TN_SOFT_ISR_PROLOGUE */ \ " pop w1; \n" \ " pop w0; \n" \ \ - /* finally, return from the ISR. */ \ + /* finally, return from the ISR. */ \ " retfie; \n" \ "1: \n" \ /* we got here by rcall when we are about to call user-provided ISR. */ \ @@ -370,7 +372,7 @@ typedef unsigned int TN_UWord; " mov.b w0, [w15-1]; \n" \ \ /* now, we eventually proceed to user-provided ISR. */ \ - /* When it returns, we get above to the macro _TN_SOFT_ISR_PROLOGUE */ \ + /* When it returns, we get above to the macro _TN_SOFT_ISR_EPILOGUE */ \ /* (because 'rcall' saved this address to the stack) */ \ From 1ef8504e7993f60a4334b939b9d1f245c5d57b5c Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sat, 1 Nov 2014 16:03:18 +0300 Subject: [PATCH 50/96] pic24: cleanup iin tn_arch_pic24.S --- src/arch/pic24_dspic/tn_arch_pic24.S | 273 +++++++++++++-------------- 1 file changed, 136 insertions(+), 137 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index cd3da06..3f3eb18 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -41,224 +41,223 @@ #define _TN_IPL_SHIFTED (_TN_IPL << 5) - .text + .text - /* External references */ + /* External references */ - .extern tn_curr_run_task - .extern tn_next_task_to_run - .extern IFS0 + .extern tn_curr_run_task + .extern tn_next_task_to_run + .extern IFS0 - /* Public functions declared in this file */ + /* Public functions declared in this file */ - .global __tn_arch_context_switch_now_nosave - .global __tn_arch_context_switch_pend - .global __tn_arch_is_int_disabled - .global __tn_arch_inside_isr - .global _tn_arch_sr_save_int_dis - .global _tn_arch_sr_restore - .global __INT0Interrupt + .global __tn_arch_context_switch_now_nosave + .global __tn_arch_context_switch_pend + .global __tn_arch_is_int_disabled + .global __tn_arch_inside_isr + .global _tn_arch_sr_save_int_dis + .global _tn_arch_sr_restore + .global __INT0Interrupt -/*---------------------------------------------------------------------------- -* Interrupts should be disabled here -*----------------------------------------------------------------------------*/ + +/* + * See comments for _tn_arch_context_switch_now_nosave() in tn_arch.h + */ __tn_arch_context_switch_now_nosave: - /* get new task's sp */ + /* NOTE: interrupts should be disabled here */ /* set SPLIM to max: effectively, turn stack pointer limit off */ - mov #0xffff, W0 - mov W0, _SPLIM - - /* ---- */ + mov #0xffff, w0 + mov w0, _SPLIM - mov _tn_next_task_to_run, W1 ; W1 = tn_next_task_to_run - mov #_tn_curr_run_task, W0 ; W0 = &tn_curr_run_task + /* set pointer to new task and its stack */ - mov W1, [W0] ; tn_curr_run_task = tn_next_task_to_run + mov _tn_next_task_to_run, w1 ; w1 = tn_next_task_to_run + mov #_tn_curr_run_task, w0 ; w0 = &tn_curr_run_task - mov [W1], W15 ; SP = *tn_next_task_to_run + mov w1, [w0] ; tn_curr_run_task = tn_next_task_to_run + mov [w1], w15 ; SP = *tn_next_task_to_run - bra __tn_sw_restore + bra __tn_context_restore -/*---------------------------------------------------------------------------- -* -*----------------------------------------------------------------------------*/ +/* + * See comments for _tn_arch_context_switch_pend() in tn_arch.h + */ __tn_arch_context_switch_pend: - push W0 + push w0 - mov #_IFS0, W0 - bset [W0], #0 ; IFS0bits.INT0IF = 1 + mov #_IFS0, w0 + bset [w0], #0 ; IFS0bits.INT0IF = 1 - pop W0 + pop w0 return -/*---------------------------------------------------------------------------- -* -*----------------------------------------------------------------------------*/ +/* + * ISR for INT0, which belongs to the kernel. + * Performs context switch to the task pointed to by `tn_next_task_to_run`. + */ __INT0Interrupt: - ;; Save current context + ;; Save current context - push _SR - push W14 - push.d W12 - push.d W10 - push.d W8 - push.d W6 - push.d W4 - push.d W2 - push.d W0 - push _RCOUNT - push _TBLPAG - push _CORCON - push _PSVPAG - push _SPLIM + push _SR + push w14 + push.d w12 + push.d w10 + push.d w8 + push.d w6 + push.d w4 + push.d w2 + push.d w0 + push _RCOUNT + push _TBLPAG + push _CORCON + push _PSVPAG + push _SPLIM - /* store sp in preemted task's TCB */ + /* store sp in preemted task's TCB */ - mov _tn_curr_run_task, W0 ; move current task stack pointer to W0 - mov W15, [W0] + mov _tn_curr_run_task, w0 ; w0 = tn_curr_run_task; + mov w15, [w0] ; tn_curr_run_task->stack_top = SR; - /* save SR in W2 */ - mov _SR, W2 + /* save SR in w2 */ + mov _SR, w2 - /* set SPLIM to max: effectively, turn stack pointer limit off */ + /* set SPLIM to max: effectively, turn stack pointer limit off */ - mov #0xffff, W0 - mov W0, _SPLIM + mov #0xffff, w0 + mov w0, _SPLIM - /* disable interrupts */ - mov _SR, W0 - xor #_TN_IPL_SHIFTED, W0 - and #0xE0, W0 - xor _SR + /* disable interrupts */ + mov _SR, w0 + xor #_TN_IPL_SHIFTED, w0 + and #0xE0, w0 + xor _SR - /* tn_curr_run_task = tn_next_task_to_run */ + /* tn_curr_run_task = tn_next_task_to_run */ - mov _tn_next_task_to_run, W1 ; W1 = tn_next_task_to_run - mov #_tn_curr_run_task, W0 ; W0 = &tn_curr_run_task + mov _tn_next_task_to_run, w1 ; w1 = tn_next_task_to_run + mov #_tn_curr_run_task, w0 ; w0 = &tn_curr_run_task - mov W1, [W0] ; tn_curr_run_task = tn_next_task_to_run + mov w1, [w0] ; tn_curr_run_task = tn_next_task_to_run - /* Set new stack pointer (from newly activated task) */ + /* Set new stack pointer (from newly activated task) */ - mov [W1], W15 ; SP = *tn_next_task_to_run + mov [w1], w15 ; SP = *tn_next_task_to_run - /* clear INT0 pending bit */ + /* clear INT0 pending bit */ - mov #_IFS0, W0 - bclr [W0], #0 ; IFS0bits.INT0IF = 0 + mov #_IFS0, w0 + bclr [w0], #0 ; IFS0bits.INT0IF = 0 - /* restore SR from W2 (and therefore enable interrupts) */ + /* restore SR from w2 (and therefore enable interrupts) */ - mov W2, _SR + mov w2, _SR -__tn_sw_restore: +__tn_context_restore: - ; Restore context on stack pointer + ; Restore context on stack pointer - pop _SPLIM - pop _PSVPAG - pop _CORCON - pop _TBLPAG - pop _RCOUNT - pop.d W0 - pop.d W2 - pop.d W4 - pop.d W6 - pop.d W8 - pop.d W10 - pop.d W12 - pop W14 - pop _SR + pop _SPLIM + pop _PSVPAG + pop _CORCON + pop _TBLPAG + pop _RCOUNT + pop.d w0 + pop.d w2 + pop.d w4 + pop.d w6 + pop.d w8 + pop.d w10 + pop.d w12 + pop w14 + pop _SR - retfie + retfie -/*---------------------------------------------------------------------------- -* -*----------------------------------------------------------------------------*/ +/* + * See comments for tn_arch_sr_save_int_dis() in tn_arch.h + */ _tn_arch_sr_save_int_dis: - push _SR + push _SR - mov _SR, W0 - xor #_TN_IPL_SHIFTED, W0 - and #0xE0, W0 - xor _SR + mov _SR, w0 + xor #_TN_IPL_SHIFTED, w0 + and #0xE0, w0 + xor _SR - pop W0 + pop w0 return -/*---------------------------------------------------------------------------- -* -*----------------------------------------------------------------------------*/ - +/* + * See comments for tn_arch_sr_restore() in tn_arch.h + */ _tn_arch_sr_restore: - push W0 - push W1 + ; w0 - saved SR + + push w1 - mov W0, W1 - and #0xE0, W1 - mov _SR, W0 - xor W0, W1, W0 - and #0xE0, W0 - xor _SR + mov w0, w1 + and #0xE0, w1 + mov _SR, w0 + xor w0, w1, w0 + and #0xE0, w0 + xor _SR - pop W1 - pop W0 + pop w1 return -/*---------------------------------------------------------------------------- -* -*----------------------------------------------------------------------------*/ +/* + * See comments for _tn_arch_is_int_disabled() in tn_arch.h + */ __tn_arch_is_int_disabled: - mov #0xE0, W0 - and _SR, WREG - lsr W0, #5, W0 - cp W0, #_TN_IPL - bra geu, 1f - mov #0, W0 - bra 2f + mov #0xE0, w0 + and _SR, WREG + lsr w0, #5, w0 + cp w0, #_TN_IPL + bra geu, 1f + mov #0, w0 + bra 2f 1: - mov #1, W0 + mov #1, w0 2: return +/* + * See comments for _tn_arch_inside_isr() in tn_arch.h + */ __tn_arch_inside_isr: - //-- here, we check if SPLIM is equal to __tn_p24_int_splim. - // If it is, we are inside ISR. + ; here, we check if SPLIM is equal to __tn_p24_int_splim. + ; If it is, we are inside ISR. - mov __tn_p24_int_splim, w0 - cp SPLIM - mov #0, W0 - bra nz, 1f - mov #1, W0 + mov __tn_p24_int_splim, w0 + cp SPLIM + mov #0, w0 + bra nz, 1f + mov #1, w0 1: return -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ From f980fe576cb4a6feea6bacbf7bdae17427cc726f Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sat, 1 Nov 2014 16:03:41 +0300 Subject: [PATCH 51/96] tn_tasks.h: removed a bit of old commented code --- src/core/tn_tasks.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/tn_tasks.h b/src/core/tn_tasks.h index 0977c45..b5d1bf2 100644 --- a/src/core/tn_tasks.h +++ b/src/core/tn_tasks.h @@ -178,9 +178,6 @@ struct TN_Task { /// /// queue is used to include task in ready/wait lists struct TN_ListItem task_queue; - // - // queue is used to include task in timer list - //struct TN_ListItem timer_queue; /// /// timer object to implement task waiting for timeout struct TN_Timer timer; From a984f383f7a457bc645b27501d799bf12d382c46 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sat, 1 Nov 2014 17:45:59 +0300 Subject: [PATCH 52/96] added tn_cfg_dispatch.h which includes both user-provided configuration and defaults. Added a PIC24-specific option TN_P24_SYS_IPL --- src/arch/pic24_dspic/tn_arch_pic24.S | 9 ++- src/arch/pic24_dspic/tn_arch_pic24.h | 7 +-- src/core/tn_cfg_dispatch.h | 87 ++++++++++++++++++++++++++++ src/core/tn_common.h | 26 +-------- src/tn_cfg_default.h | 42 ++++++++++++++ 5 files changed, 135 insertions(+), 36 deletions(-) create mode 100644 src/core/tn_cfg_dispatch.h diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 3f3eb18..5945095 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -34,11 +34,10 @@ * ******************************************************************************/ -//TODO: this symbol is now defined in two places -//(tn_arch_pic24.h, tn_arch_pic24.S) -//need to fix it -#define _TN_IPL 0x04 -#define _TN_IPL_SHIFTED (_TN_IPL << 5) +#include "tn_cfg_dispatch.h" + +#define _TN_IPL TN_P24_SYS_IPL +#define _TN_IPL_SHIFTED (TN_P24_SYS_IPL << 5) .text diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index d3f5793..3dd4b67 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -252,11 +252,6 @@ typedef unsigned int TN_UWord; //-- internal interrupt macro stuff {{{ -//TODO: this symbol is now defined in two places -//(tn_arch_pic24.h, tn_arch_pic24.S) -//need to fix it -#define _TN_IPL "0x04" - #if TN_CHECK_PARAM /** @@ -276,7 +271,7 @@ typedef unsigned int TN_UWord; " mov #0xE0, W0 \n" \ " and _SR, WREG \n" \ " lsr W0, #5, W0 \n" \ - " cp W0, #" _TN_IPL " \n" \ + " cp W0, #" TN_P24_SYS_IPL_STR " \n" \ " bra leu, 1f \n" \ \ /* Interrupt priority is too high. Halt the debugger here. */ \ diff --git a/src/core/tn_cfg_dispatch.h b/src/core/tn_cfg_dispatch.h new file mode 100644 index 0000000..d752c63 --- /dev/null +++ b/src/core/tn_cfg_dispatch.h @@ -0,0 +1,87 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * \file + * + * Dispatch configuration: set predefined options, include user-provided cfg + * file as well as default cfg file. + * + */ + +#ifndef _TN_CFG_DISPATCH_H +#define _TN_CFG_DISPATCH_H + + +//-- Configuration constants +/** + * In this case, you should use macro like this: `#TN_MAKE_ALIG(struct my_struct)`. + * This way is used in the majority of TNKernel ports. (actually, in all ports + * except the one by AlexB) + */ +#define TN_API_MAKE_ALIG_ARG__TYPE 1 + +/** + * In this case, you should use macro like this: `#TN_MAKE_ALIG(sizeof(struct + * my_struct))`. This way is stated in TNKernel docs and used in the port for + * dsPIC/PIC24/PIC32 by AlexB. + */ +#define TN_API_MAKE_ALIG_ARG__SIZE 2 + + +//--- As a starting point, you might want to copy tn_cfg_default.h -> tn_cfg.h, +// and then edit it if you want to change default configuration. +// NOTE: the file tn_cfg.h is specified in .hgignore file, in order to not include +// project-specific configuration in the common TNKernel repository. +#include "tn_cfg.h" + +//--- default cfg file is included too, so that you are free to not set +// all available options in your tn_cfg.h file. +#include "tn_cfg_default.h" + + +#if defined (__XC16__) +# if TN_P24_SYS_IPL >= 7 +# error TN_P24_SYS_IPL must be less than 7 +# endif +# if TN_P24_SYS_IPL <= 0 +# error TN_P24_SYS_IPL must be more than 0 +# endif +#endif + +#endif // _TN_CFG_DISPATCH_H + + diff --git a/src/core/tn_common.h b/src/core/tn_common.h index 881101b..009d9a8 100644 --- a/src/core/tn_common.h +++ b/src/core/tn_common.h @@ -47,31 +47,7 @@ * INCLUDED FILES ******************************************************************************/ -//-- Configuration constants -/** - * In this case, you should use macro like this: `#TN_MAKE_ALIG(struct my_struct)`. - * This way is used in the majority of TNKernel ports. (actually, in all ports - * except the one by AlexB) - */ -#define TN_API_MAKE_ALIG_ARG__TYPE 1 - -/** - * In this case, you should use macro like this: `#TN_MAKE_ALIG(sizeof(struct - * my_struct))`. This way is stated in TNKernel docs and used in the port for - * dsPIC/PIC24/PIC32 by AlexB. - */ -#define TN_API_MAKE_ALIG_ARG__SIZE 2 - -//--- As a starting point, you might want to copy tn_cfg_default.h -> tn_cfg.h, -// and then edit it if you want to change default configuration. -// NOTE: the file tn_cfg.h is specified in .hgignore file, in order to not include -// project-specific configuration in the common TNKernel repository. -#include "tn_cfg.h" - -//--- default cfg file is included too, so that you are free to not set -// all available options in your tn_cfg.h file. -#include "tn_cfg_default.h" - +#include "tn_cfg_dispatch.h" #ifdef __cplusplus extern "C" { /*}*/ diff --git a/src/tn_cfg_default.h b/src/tn_cfg_default.h index d14d3d9..58ab07b 100644 --- a/src/tn_cfg_default.h +++ b/src/tn_cfg_default.h @@ -206,6 +206,48 @@ #endif + + + +/******************************************************************************* + * PIC24/dsPIC-specific configuration + ******************************************************************************/ + + +/** + * PIC24/dsPIC TNeoKernel port allows to specify the range of "system interrupt + * priorities"; and kernel services are allowed to call only from interrupts of + * these priorities. These interrupts will be referred to as "system + * interrupts". + * + * System interrupts get disabled by the kernel for short periods of time, + * when kernel needs to modify critical data. + * + * The range is specified by just a single number: `TN_P24_SYS_IPL`. Here is + * a list of priorities and their characteristics: + * + * - priorities `[1 .. TN_P24_SYS_IPL]`: kernel services **are** allowed to call. + * Interrupts get disabled for short periods of time when modifying critical + * kernel data (for about 100 cycles or the like) + * - priorities `(TN_P24_SYS_IPL .. 6]`: kernel services **are not** allowed + * to call. Interrupts are not disabled when modifying critical kernel data, + * but they are disabled for 4..8 cycles by `disi` instruction when + * entering/exiting system ISR: we need to safely modify `SP` and `SPLIM`. + * - priority `7`: Interrupts are never disabled by the kernel. Note that `disi` + * instruction leaves interrupts of priority 7 enabled. + * + * Maximum system interrupt priority. Should be >= 1 and <= 6. Default: 4. + * + */ +#ifndef TN_P24_SYS_IPL +//-- NOTE: the following two macros should correspond: they should specify +// the same number, but in one case it is an integer, and in the second case +// it is a string. If anyone knows how to write it so that we can specify +// just a single macro, please let me know. :) +# define TN_P24_SYS_IPL 4 +# define TN_P24_SYS_IPL_STR "4" +#endif + #endif // _TN_CFG_DEFAULT_H From 551079174e086dcc4d6f5d75a938b522b2833401 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sat, 1 Nov 2014 18:06:19 +0300 Subject: [PATCH 53/96] added pic24_details.dox --- src/tn_cfg_default.h | 28 +++--------- stuff/doc_pages/mainpage.dox | 5 ++- stuff/doc_pages/pic24_details.dox | 72 +++++++++++++++++++++++++++++++ stuff/doxygen/tn_doxyfile | 1 + 4 files changed, 82 insertions(+), 24 deletions(-) create mode 100644 stuff/doc_pages/pic24_details.dox diff --git a/src/tn_cfg_default.h b/src/tn_cfg_default.h index 58ab07b..53fea4c 100644 --- a/src/tn_cfg_default.h +++ b/src/tn_cfg_default.h @@ -215,28 +215,12 @@ /** - * PIC24/dsPIC TNeoKernel port allows to specify the range of "system interrupt - * priorities"; and kernel services are allowed to call only from interrupts of - * these priorities. These interrupts will be referred to as "system - * interrupts". - * - * System interrupts get disabled by the kernel for short periods of time, - * when kernel needs to modify critical data. - * - * The range is specified by just a single number: `TN_P24_SYS_IPL`. Here is - * a list of priorities and their characteristics: - * - * - priorities `[1 .. TN_P24_SYS_IPL]`: kernel services **are** allowed to call. - * Interrupts get disabled for short periods of time when modifying critical - * kernel data (for about 100 cycles or the like) - * - priorities `(TN_P24_SYS_IPL .. 6]`: kernel services **are not** allowed - * to call. Interrupts are not disabled when modifying critical kernel data, - * but they are disabled for 4..8 cycles by `disi` instruction when - * entering/exiting system ISR: we need to safely modify `SP` and `SPLIM`. - * - priority `7`: Interrupts are never disabled by the kernel. Note that `disi` - * instruction leaves interrupts of priority 7 enabled. - * - * Maximum system interrupt priority. Should be >= 1 and <= 6. Default: 4. + * + * Maximum system interrupt priority. For details on system interrupts on + * PIC24/dsPIC, refer to the section \ref pic24_interrupts + * "PIC24/dsPIC interrupts". + * + * Should be >= 1 and <= 6. Default: 4. * */ #ifndef TN_P24_SYS_IPL diff --git a/stuff/doc_pages/mainpage.dox b/stuff/doc_pages/mainpage.dox index 0a39bea..4c27d88 100644 --- a/stuff/doc_pages/mainpage.dox +++ b/stuff/doc_pages/mainpage.dox @@ -10,8 +10,8 @@ TNeoKernel was born as a thorough review and re-implementation of \ref why_reimplement__bugs "inherited bugs" are fixed as well as new features being added, it is well documented and tested carefully with unit-tests. -Currently it is available for PIC32 only, but will probably be ported to other -architectures. Tested on PIC32MX. +Currently it is available for PIC32/PIC24/dsPIC, will be ported at least to ARM +Cortex M3. API is \ref tnkernel_diff "changed somewhat", so it's not 100% compatible with TNKernel, hence the new name: TNeoKernel. @@ -25,6 +25,7 @@ Related pages: - \ref interrupts - \ref building - \ref pic32_details + - \ref pic24_details - \ref why_reimplement - \ref tnkernel_diff - \ref unit_tests diff --git a/stuff/doc_pages/pic24_details.dox b/stuff/doc_pages/pic24_details.dox new file mode 100644 index 0000000..f041367 --- /dev/null +++ b/stuff/doc_pages/pic24_details.dox @@ -0,0 +1,72 @@ +/** +\page pic24_details PIC24/dsPIC details + +\tableofcontents + +PIC24/dsPIC port implementation details + +\section pic24_context_switch Context switch +The context switch is implemented using the external interrupt 0 (`INT0`). It +is handled completely by the kernel, application should never touch it. + +\section pic24_interrupts Interrupts + +For detailed information about interrupts in TNeoKernel, refer to the page \ref +interrupts. + +PIC24/dsPIC TNeoKernel port supports nested interrupts. It allows to specify +the range of "system interrupt priorities"; and kernel services are allowed to +call only from interrupts of these priorities. These interrupts will be +referred to as "system interrupts". + +System interrupts get disabled by the kernel for short periods of time, +when kernel needs to modify critical data. + +System interrupts use separate interrupt stack instead of the task's stack. +This approach saves a lot of RAM. + +The range is specified by just a single number: `#TN_P24_SYS_IPL`. Here is +a list of priorities and their characteristics: + +- priorities `[1 .. #TN_P24_SYS_IPL]`: + - Kernel services **are** allowed to call; + - Separate interrupt stack is used by ISR; + - Interrupts get disabled for short periods of time when modifying critical + kernel data (for about 100 cycles or the like). +- priorities `(#TN_P24_SYS_IPL .. 6]`: + - Kernel services **are not** allowed to call; + - Task's stack is used by ISR; + - Interrupts are not disabled when modifying critical kernel data, but they + are disabled for 4..8 cycles by `disi` instruction when entering/exiting + system ISR: we need to safely modify `SP` and `SPLIM`. +- priority `7`: + - Kernel services **are not** allowed to call; + - Task's stack is used by ISR; + - Interrupts are never disabled by the kernel. Note that `disi` instruction + leaves interrupts of priority 7 enabled. + +The kernel provides C-language macro for calling C-language **system** +interrupt service routines. + +Usage is as follows: + +\code{.c} +/* + * Timer 1 interrupt handler using software interrupt context saving, + * PSV is handled automatically: + */ +tn_soft_isr(_T1Interrupt, auto_psv) +{ + //-- clear interrupt flag + IFS0bits.T1IF = 0; + + //-- do something useful +} +\endcode + +\attention do **not** use this macro for non-system interrupt (that is, for +interrupt of priority higher than `#TN_P24_SYS_IPL`). Use standard way to +define it. If you violate this rule, debugger will be halted by the kernel when +entering ISR. In release build, CPU is just reset. + +*/ diff --git a/stuff/doxygen/tn_doxyfile b/stuff/doxygen/tn_doxyfile index 78dcdd6..9798546 100644 --- a/stuff/doxygen/tn_doxyfile +++ b/stuff/doxygen/tn_doxyfile @@ -766,6 +766,7 @@ INPUT = ../../src \ ../../stuff/doc_pages/interrupts.dox \ ../../stuff/doc_pages/building.dox \ ../../stuff/doc_pages/pic32_details.dox \ + ../../stuff/doc_pages/pic24_details.dox \ ../../stuff/doc_pages/why_reimplement.dox \ ../../stuff/doc_pages/tnkernel_diff.dox \ ../../stuff/doc_pages/unit_tests.dox \ From cc410ad57d5e6205e64633f899930345e893bf84 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sat, 1 Nov 2014 23:44:46 +0300 Subject: [PATCH 54/96] added tn_arch_detect.h, improved interrupts docs. tn_cfg_dispatch.h checks whether each option is defined --- README.md | 4 +- src/arch/pic24_dspic/tn_arch_pic24.S | 10 +++ src/arch/pic24_dspic/tn_arch_pic24.h | 10 ++- src/arch/pic24_dspic/tn_arch_pic24_c.c | 2 - src/arch/pic32/tn_arch_pic32.c | 7 ++ src/arch/pic32/tn_arch_pic32.h | 4 +- src/arch/tn_arch.h | 49 ++++++++----- src/arch/tn_arch_detect.h | 99 ++++++++++++++++++++++++++ src/core/tn_cfg_dispatch.h | 67 ++++++++++++++++- src/core/tn_common.h | 1 + src/tn_cfg_default.h | 17 +++++ stuff/doc_pages/interrupts.dox | 53 ++++++-------- stuff/doc_pages/mainpage.dox | 4 +- stuff/doc_pages/pic24_details.dox | 18 +++-- stuff/doc_pages/pic32_details.dox | 35 +++++++-- 15 files changed, 302 insertions(+), 78 deletions(-) create mode 100644 src/arch/tn_arch_detect.h diff --git a/README.md b/README.md index 3b683f2..19242ae 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ round-robin scheduling for the tasks with identical priority. TNeoKernel was born as a thorough review and re-implementation of [TNKernel](http://tnkernel.com) v2.7. The new kernel has well-formed code, inherited bugs are fixed as well as new features being added, it is well documented and tested carefully with unit-tests. -Currently it is available for PIC32 only, but will probably be ported to other architectures. Tested on PIC32MX. +Currently it is available for PIC32/PIC24/dsPIC, and it will be ported at least to ARM Cortex M3. Comprehensive documentation is available in two forms: html and pdf. @@ -40,7 +40,7 @@ new name for this project, in order to avoid confusion, hence "TNeoKernel". Refer to the [Differences from TNKernel API](http://dfrank.bitbucket.org/tneokernel_api/latest/html/tnkernel_diff.html) page for details. Together with almost totally re-writing TNKernel, I've implemented detailed -[unit tests](http://dfrank.bitbucket.org/tneokernel_api/latest/html/unit_tests.html) for it, to make sure I didn't break anything, and of course I've found several bugs in original TNKernel 2.7: refer to the section [Bugs of TNKernel 2.7](http://dfrank.bitbucket.org/tneokernel_api/latest/html/why_reimplement.html#why_reimplement__bugs). Unit tests are, or course, a "must-have" for the project like this; it's so strange bug original TNKernel seems untested. +[unit tests](http://dfrank.bitbucket.org/tneokernel_api/latest/html/unit_tests.html) for it, to make sure I didn't break anything, and of course I've found several bugs in original TNKernel 2.7: refer to the section [Bugs of TNKernel 2.7](http://dfrank.bitbucket.org/tneokernel_api/latest/html/why_reimplement.html#why_reimplement__bugs). Unit tests are, or course, a "must-have" for the project like this; it's so strange but original TNKernel seems untested. Note that PIC32-dependent routines (such as context switch and so on) are originally implemented by Anders Montonen; I examined them in detail and diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 5945095..684b721 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -251,6 +251,16 @@ __tn_arch_inside_isr: ; here, we check if SPLIM is equal to __tn_p24_int_splim. ; If it is, we are inside ISR. + ; + ; NOTE: we can't check IPL from SR, because when someone disables interrupts + ; by calling tn_arch_sr_save_int_dis(), IPL is modified. So, if we disable + ; interrupts from task, then _tn_arch_inside_isr() would return true, + ; but it is actually should be false. + ; + ; Instead, on PIC24/dsPIC, system interrupts **must** use kernel-provided + ; macro tn_soft_isr() for interrupt definition, and we modify SPLIM there. + ; So, here we check SPLIM, and if it points to _tn_p24_int_splim, + ; we are inside interrupt. mov __tn_p24_int_splim, w0 cp SPLIM diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 3dd4b67..919aa83 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -45,9 +45,7 @@ #ifndef _TN_ARCH_PIC32_H #define _TN_ARCH_PIC32_H -//-- this include is needed to get build-time configuration -// (TN_DEBUG is used) -#include "../../core/tn_common.h" +#include "../../core/tn_cfg_dispatch.h" #ifdef __cplusplus @@ -122,7 +120,7 @@ extern "C" { /*}*/ * Minimum task's stack size, in words, not in bytes; includes a space for * context plus for parameters passed to task's body function. */ -#define TN_MIN_STACK_SIZE 36//TODO +#define TN_MIN_STACK_SIZE 23 /** * Width of `int` type. @@ -406,7 +404,7 @@ typedef unsigned int TN_UWord; * Usage looks like the following: * * \code{.c} - * tn_soft_isr(_T1Interrupt, auto_psv) + * tn_p24_soft_isr(_T1Interrupt, auto_psv) * { * //-- clear interrupt flag * IFS0bits.T1IF = 0; @@ -427,7 +425,7 @@ typedef unsigned int TN_UWord; * * */ -#define tn_soft_isr(_func, _psv) _tn_soft_isr_internal(_func, _psv, ) +#define tn_p24_soft_isr(_func, _psv) _tn_soft_isr_internal(_func, _psv, ) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 609a393..5cbaccc 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -110,8 +110,6 @@ TN_UWord *_tn_arch_stack_init( void tn_arch_int_dis(void) { - //__builtin_disable_interrupts(); - //TODO tn_arch_sr_save_int_dis(); } diff --git a/src/arch/pic32/tn_arch_pic32.c b/src/arch/pic32/tn_arch_pic32.c index 0b51c18..b843e78 100644 --- a/src/arch/pic32/tn_arch_pic32.c +++ b/src/arch/pic32/tn_arch_pic32.c @@ -151,6 +151,13 @@ void _tn_arch_sys_init( // SP + 00 lo //---------------------------------------------------------------------------- +/* + * See comments in the `tn_arch.h` file + * + * **NOTE** that returned *top of the stack* is NOT the address which may be + * used for storing the new data. Instead, it is the *previous* address. + * + */ TN_UWord *_tn_arch_stack_top_get( TN_UWord *stack_low_address, int stack_size diff --git a/src/arch/pic32/tn_arch_pic32.h b/src/arch/pic32/tn_arch_pic32.h index 5155e90..5820d80 100644 --- a/src/arch/pic32/tn_arch_pic32.h +++ b/src/arch/pic32/tn_arch_pic32.h @@ -50,9 +50,7 @@ * INCLUDED FILES ******************************************************************************/ -//-- this include is needed to get build-time configuration -// (TN_DEBUG is used) -#include "../../core/tn_common.h" +#include "../../core/tn_cfg_dispatch.h" diff --git a/src/arch/tn_arch.h b/src/arch/tn_arch.h index f62b5c2..0312e1f 100644 --- a/src/arch/tn_arch.h +++ b/src/arch/tn_arch.h @@ -56,12 +56,12 @@ * ACTUAL PORT IMPLEMENTATION ******************************************************************************/ -#if defined(__PIC32MX__) -#include "pic32/tn_arch_pic32.h" -#elif defined(__C30__) -#include "pic24_dspic/tn_arch_pic24.h" +#if defined(__TN_ARCH_PIC32MX__) +# include "pic32/tn_arch_pic32.h" +#elif defined(__TN_ARCH_PIC24_DSPIC__) +# include "pic24_dspic/tn_arch_pic24.h" #else -#error "unknown platform" +# error "unknown platform" #endif @@ -76,25 +76,34 @@ extern "C" { /*}*/ /** - * Unconditionally disable interrupts + * Unconditionally disable system interrupts. + * + * Refer to the section \ref interrupt_types for details on what is system + * interrupt. */ void tn_arch_int_dis(void); /** * Unconditionally enable interrupts + * + * Refer to the section \ref interrupt_types for details on what is system + * interrupt. */ void tn_arch_int_en(void); /** - * Disable interrupts and return previous value of status register, - * atomically + * Disable system interrupts and return previous value of status + * register, atomically. + * + * Refer to the section \ref interrupt_types for details on what is system + * interrupt. * * @see `tn_arch_sr_restore()` */ TN_UWord tn_arch_sr_save_int_dis(void); /** - * Restore previously saved status register + * Restore previously saved status register. * * @param sr status register value previously from * `tn_arch_sr_save_int_dis()` @@ -103,8 +112,8 @@ TN_UWord tn_arch_sr_save_int_dis(void); */ void tn_arch_sr_restore(TN_UWord sr); -/* - * Architecture-dependent system startup routine. +/** + * Architecture-dependent system startup routine. Called from `tn_sys_start()`. */ void _tn_arch_sys_init( TN_UWord *int_stack, @@ -113,16 +122,15 @@ void _tn_arch_sys_init( /** - * Should return top of the stack, which may be either: + * Should return top of the stack, which may be: * * - `(stack_low_address - 1)` * - `(stack_low_address + stack_size)` + * - `(stack_low_address)` + * - `(stack_low_address + stack_size - 1)` * * (depending on the architecture) * - * **NOTE** that returned *top of the stack* is NOT the address which may be - * used for storing the new data. Instead, it is the *previous* address. - * * @param stack_low_address * Start address of the stack array. * @param stack_size @@ -165,12 +173,19 @@ TN_UWord *_tn_arch_stack_init( ); /** - * Should return 1 if ISR is currently running, 0 otherwise + * Should return 1 if system ISR is currently running, 0 otherwise. + * + * Refer to the section \ref interrupt_types for details on what is system + * ISR. */ int _tn_arch_inside_isr(void); /** - * TODO + * Should return 1 if system interrupts are currently disabled, 0 + * otherwise. + * + * Refer to the section \ref interrupt_types for details on what is system + * interrupt. */ int _tn_arch_is_int_disabled(void); diff --git a/src/arch/tn_arch_detect.h b/src/arch/tn_arch_detect.h new file mode 100644 index 0000000..04d3243 --- /dev/null +++ b/src/arch/tn_arch_detect.h @@ -0,0 +1,99 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * \file + * + * Define macros for platform identification. + */ + +#ifndef _TN_ARCH_DETECT_H +#define _TN_ARCH_DETECT_H + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +#undef __TN_ARCH_PIC24_DSPIC__ +#undef __TN_ARCH_PIC32MX__ + + +#if defined(__PIC24F__) + +# define __TN_ARCH_PIC24_DSPIC__ + +#elif defined (__PIC24E__) + +# define __TN_ARCH_PIC24_DSPIC__ + +#elif defined (__PIC24H__) + +# define __TN_ARCH_PIC24_DSPIC__ + +#elif defined (__dsPIC30F__) + +# define __TN_ARCH_PIC24_DSPIC__ + +#elif defined (__dsPIC33E__) + +# define __TN_ARCH_PIC24_DSPIC__ + +#elif defined (__dsPIC33F__) + +# define __TN_ARCH_PIC24_DSPIC__ + +#elif defined (__PIC32MX__) + +# define __TN_ARCH_PIC32MX__ + +#else +# error unknown platform +#endif + + + + + + + + + + +#endif /* _TN_ARCH_DETECT_H */ + diff --git a/src/core/tn_cfg_dispatch.h b/src/core/tn_cfg_dispatch.h index d752c63..eab26ed 100644 --- a/src/core/tn_cfg_dispatch.h +++ b/src/core/tn_cfg_dispatch.h @@ -45,6 +45,7 @@ #ifndef _TN_CFG_DISPATCH_H #define _TN_CFG_DISPATCH_H +#include "../arch/tn_arch_detect.h" //-- Configuration constants /** @@ -68,12 +69,73 @@ // project-specific configuration in the common TNKernel repository. #include "tn_cfg.h" +//-- Probably a bit of hack, but anyway: +// tn_cfg.h might just be a modified copy from existing tn_cfg_default.h, +// and then, _TN_CFG_DEFAULT_H is probably defined there. +// But we need to set some defaults, so, let's undef it. +// Anyway, tn_cfg_default.h checks whether each particular option is already +// defined, so it works nice. +#undef _TN_CFG_DEFAULT_H + //--- default cfg file is included too, so that you are free to not set // all available options in your tn_cfg.h file. #include "tn_cfg_default.h" +//-- check that all options specified {{{ + +#if !defined(TN_PRIORITIES_CNT) +# error TN_PRIORITIES_CNT is not defined +#endif + +#if !defined(TN_CHECK_PARAM) +# error TN_CHECK_PARAM is not defined +#endif + +#if !defined(TN_DEBUG) +# error TN_DEBUG is not defined +#endif + +#if !defined(TN_OLD_TNKERNEL_NAMES) +# error TN_OLD_TNKERNEL_NAMES is not defined +#endif + +#if !defined(TN_USE_MUTEXES) +# error TN_USE_MUTEXES is not defined +#endif + +#if TN_USE_MUTEXES +# if !defined(TN_MUTEX_REC) +# error TN_MUTEX_REC is not defined +# endif +# if !defined(TN_MUTEX_DEADLOCK_DETECT) +# error TN_MUTEX_DEADLOCK_DETECT is not defined +# endif +#endif -#if defined (__XC16__) +#if !defined(TN_TICK_LISTS_CNT) +# error TN_TICK_LISTS_CNT is not defined +#endif + +#if !defined(TN_API_MAKE_ALIG_ARG) +# error TN_API_MAKE_ALIG_ARG is not defined +#endif + +#if defined (__TN_ARCH_PIC24_DSPIC__) +# if !defined(TN_P24_SYS_IPL) +# error TN_P24_SYS_IPL is not defined +# endif + +# if !defined(TN_P24_SYS_IPL_STR) +# error TN_P24_SYS_IPL_STR is not defined +# endif +#endif + +// }}} + + + + +#if defined (__TN_ARCH_PIC24_DSPIC__) # if TN_P24_SYS_IPL >= 7 # error TN_P24_SYS_IPL must be less than 7 # endif @@ -82,6 +144,9 @@ # endif #endif + + + #endif // _TN_CFG_DISPATCH_H diff --git a/src/core/tn_common.h b/src/core/tn_common.h index 009d9a8..5b17e08 100644 --- a/src/core/tn_common.h +++ b/src/core/tn_common.h @@ -47,6 +47,7 @@ * INCLUDED FILES ******************************************************************************/ +#include "../arch/tn_arch_detect.h" #include "tn_cfg_dispatch.h" #ifdef __cplusplus diff --git a/src/tn_cfg_default.h b/src/tn_cfg_default.h index 53fea4c..3fc0254 100644 --- a/src/tn_cfg_default.h +++ b/src/tn_cfg_default.h @@ -215,14 +215,31 @@ /** + * \def TN_P24_SYS_IPL * * Maximum system interrupt priority. For details on system interrupts on * PIC24/dsPIC, refer to the section \ref pic24_interrupts * "PIC24/dsPIC interrupts". * + * \attention you should also set `#TN_P24_SYS_IPL_STR` to appropriate value. + * * Should be >= 1 and <= 6. Default: 4. * */ + +/** + * \def TN_P24_SYS_IPL_STR + * + * The same as `#TN_P24_SYS_IPL` but should be set as string, for example: + * \code{.c} + * #define TN_P24_SYS_IPL_STR "4" + * \endcode + * + * It is used in assembly for ISR macro `tn_p24_soft_isr()`. + * I don't like that we have to keep two macros instead of just one, so if + * anybody knows how to use integer value there, please let me know :) + */ + #ifndef TN_P24_SYS_IPL //-- NOTE: the following two macros should correspond: they should specify // the same number, but in one case it is an integer, and in the second case diff --git a/stuff/doc_pages/interrupts.dox b/stuff/doc_pages/interrupts.dox index 200ad3d..345b2b4 100644 --- a/stuff/doc_pages/interrupts.dox +++ b/stuff/doc_pages/interrupts.dox @@ -10,45 +10,32 @@ could save a lot of RAM: interrupt can happen at any moment of time, and if there's no separate interrupt stack, then each task should have enough stack space for the worse case of interrupt nesting. -Assume application's ISRs take max 64 words (64 * 4 = 256 bytes on PIC32) and application has 4 -tasks (plus one idle task). Then, each of 5 tasks must have 64 words for -interrupts: 64 * 5 * 4 = 1280 bytes of RAM just for 64 words for ISR. +Assume application's ISRs take max 64 words (64 * 4 = 256 bytes on PIC32) and +application has 4 tasks (plus one idle task). Then, each of 5 tasks must have +64 words for interrupts: 64 * 5 * 4 = 1280 bytes of RAM just for 64 words for +ISR. With separate stack for interrupts, these 64 words should be allocated just once. Interrupt stack array should be given to `#tn_sys_start()`. For additional information, refer to the section \ref starting_the_kernel. In order to make particular ISR use separate interrupt stack, this ISR should -be defined by kernel-provided macro, which is platform-dependent: see \ref -pic32_details. - -In spite of the fact that the kernel provides separate stack for interrupt, -this isn't a mandatory: you're able to define your ISR in a standard way, -making it use stask of interrupted task and work a bit faster. There is always -a tradeoff. There are **no additional constraints** on ISR defined without -kernel-provided macro: in either ISR, you can call the same set of kernel -services. - -When you make a decision on whether particular ISR should use separate stack, -consider the following: - -- When ISR is defined in a standard way, and no function is called from that - ISR, only necessary registers are saved on stack. If you have such an ISR - (that doesn't call any function), and this ISR should work very fast, - consider using standard way instead of kernel-provided macro. -- When ISR is defined in a standard way, but it calls any function and doesn't - use shadow register set, compiler saves (almost) full context **on the task's - stack**, because it doesn't know which registers are used inside the function. - In this case, it usually makes more sense to use kernel-provided macro (see - below). -- Kernel-provided interrupt macros switch stack pointer between interrupt stack - and task stack automatically, it takes additional time: e.g. on PIC32 it's - about 20 cycles. -- Kernel-provided interrupt macro that doesn't use shadow register set always - saves (almost) full context **on the interrupt stack**, independently of - whether any function is called from an ISR. -- Kernel-provided interrupt macro that uses shadow register set saves a little - amount of registers **on the interrupt stack**. +be defined by kernel-provided macro, which is platform-dependent: see: +- \ref pic32_interrupts "PIC32 interrupts", +- \ref pic24_interrupts "PIC24/dsPIC interrupts". + +\section interrupt_types Interrupt types + +On some platforms (namely, on PIC24/dsPIC), there are two types of interrups: +system interrupts and user interrupts. Other platforms have +system interrupts only. Kernel services are allowed to call only from +system interrupts, and interrupt-related kernel services +(`tn_arch_sr_save_int_dis()`, `tn_arch_sr_restore()`, `_tn_arch_inside_isr()`, +etc) affect only system interrupts. Say, if +`_tn_arch_inside_isr()` is called from user interrupt, it returns `0`. + +Particular platform might have additional constraints for each of these +interrupt types, refer to the details of each supported platform for details. */ diff --git a/stuff/doc_pages/mainpage.dox b/stuff/doc_pages/mainpage.dox index 4c27d88..d5139ba 100644 --- a/stuff/doc_pages/mainpage.dox +++ b/stuff/doc_pages/mainpage.dox @@ -10,8 +10,8 @@ TNeoKernel was born as a thorough review and re-implementation of \ref why_reimplement__bugs "inherited bugs" are fixed as well as new features being added, it is well documented and tested carefully with unit-tests. -Currently it is available for PIC32/PIC24/dsPIC, will be ported at least to ARM -Cortex M3. +Currently it is available for PIC32/PIC24/dsPIC, and it will be ported at least +to ARM Cortex M3. API is \ref tnkernel_diff "changed somewhat", so it's not 100% compatible with TNKernel, hence the new name: TNeoKernel. diff --git a/stuff/doc_pages/pic24_details.dox b/stuff/doc_pages/pic24_details.dox index f041367..6ad1fc3 100644 --- a/stuff/doc_pages/pic24_details.dox +++ b/stuff/doc_pages/pic24_details.dox @@ -15,32 +15,36 @@ For detailed information about interrupts in TNeoKernel, refer to the page \ref interrupts. PIC24/dsPIC TNeoKernel port supports nested interrupts. It allows to specify -the range of "system interrupt priorities"; and kernel services are allowed to +the range of *system interrupt priorities*; and kernel services are allowed to call only from interrupts of these priorities. These interrupts will be -referred to as "system interrupts". +referred to as *system interrupts*. System interrupts get disabled by the kernel for short periods of time, -when kernel needs to modify critical data. +when kernel needs to modify critical data. It's about 100 cycles at most. System interrupts use separate interrupt stack instead of the task's stack. This approach saves a lot of RAM. -The range is specified by just a single number: `#TN_P24_SYS_IPL`. Here is -a list of priorities and their characteristics: +The range is specified by just a single number: `#TN_P24_SYS_IPL`, which +represents maximum *system interrupt priority*. Here is a list of priorities +and their characteristics: - priorities `[1 .. #TN_P24_SYS_IPL]`: - Kernel services **are** allowed to call; + - The macro `tn_p24_soft_isr()` must be used. - Separate interrupt stack is used by ISR; - Interrupts get disabled for short periods of time when modifying critical kernel data (for about 100 cycles or the like). -- priorities `(#TN_P24_SYS_IPL .. 6]`: +- priorities `[(#TN_P24_SYS_IPL + 1) .. 6]`: - Kernel services **are not** allowed to call; + - The macro `tn_p24_soft_isr()` must not be used. - Task's stack is used by ISR; - Interrupts are not disabled when modifying critical kernel data, but they are disabled for 4..8 cycles by `disi` instruction when entering/exiting system ISR: we need to safely modify `SP` and `SPLIM`. - priority `7`: - Kernel services **are not** allowed to call; + - The macro `tn_p24_soft_isr()` must not be used. - Task's stack is used by ISR; - Interrupts are never disabled by the kernel. Note that `disi` instruction leaves interrupts of priority 7 enabled. @@ -55,7 +59,7 @@ Usage is as follows: * Timer 1 interrupt handler using software interrupt context saving, * PSV is handled automatically: */ -tn_soft_isr(_T1Interrupt, auto_psv) +tn_p24_soft_isr(_T1Interrupt, auto_psv) { //-- clear interrupt flag IFS0bits.T1IF = 0; diff --git a/stuff/doc_pages/pic32_details.dox b/stuff/doc_pages/pic32_details.dox index cda32e5..ed2e3f8 100644 --- a/stuff/doc_pages/pic32_details.dox +++ b/stuff/doc_pages/pic32_details.dox @@ -35,9 +35,11 @@ it's time to switch context. \section pic32_interrupts Interrupts -For detailed information about interrupts in TNeoKernel, refer to the page \ref +For generic information about interrupts in TNeoKernel, refer to the page \ref interrupts. +PIC32 port has system interrupts only, there are no user interrupts. + PIC32 port supports nested interrupts. The kernel provides C-language macros for calling C-language interrupt service routines, which can use either MIPS32 or MIPS16e mode. Both software and shadow register interrupt context @@ -57,7 +59,9 @@ tn_srs_isr(_UART_1_VECTOR) } \endcode -Alternatively, you can define your ISR in a standard way, like this: +In spite of the fact that the kernel provides separate stack for interrupt, +this isn't a mandatory on PIC32: you're able to define your ISR in a standard +way, making it use stask of interrupted task and work a bit faster. Like this: \code{.c} void __ISR(_TIMER_1_VECTOR) timer_1_isr(void) @@ -66,8 +70,29 @@ void __ISR(_TIMER_1_VECTOR) timer_1_isr(void) } \endcode -Then, context is saved on the task's stack instead of interrupt stack (and -takes therefore much more RAM), but you save about 20 cycles for each -interrupt. See the page \ref interrupts for details. +There is always a tradeoff. There are **no additional constraints** on ISR +defined without kernel-provided macro: in either ISR, you can call the same set +of kernel services. + +When you make a decision on whether particular ISR should use separate stack, +consider the following: + +- When ISR is defined in a standard way, and no function is called from that + ISR, only necessary registers are saved on stack. If you have such an ISR + (that doesn't call any function), and this ISR should work very fast, + consider using standard way instead of kernel-provided macro. +- When ISR is defined in a standard way, but it calls any function and doesn't + use shadow register set, compiler saves (almost) full context **on the task's + stack**, because it doesn't know which registers are used inside the function. + In this case, it usually makes more sense to use kernel-provided macro (see + below). +- Kernel-provided interrupt macros switch stack pointer between interrupt stack + and task stack automatically, it takes additional time: e.g. on PIC32 it's + about 20 cycles. +- Kernel-provided interrupt macro that doesn't use shadow register set always + saves (almost) full context **on the interrupt stack**, independently of + whether any function is called from an ISR. +- Kernel-provided interrupt macro that uses shadow register set saves a little + amount of registers **on the interrupt stack**. */ From 55e6bca0849050ee5a3e49c5ae112e214dc7de2a Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 00:45:48 +0300 Subject: [PATCH 55/96] pic24: little optimization in assembler routines --- README.md | 2 ++ src/arch/pic24_dspic/tn_arch_pic24.S | 26 +++++++++++--------- src/arch/pic24_dspic/tn_arch_pic24_c.c | 34 ++++++++++++++++++++++---- stuff/doxygen/tn_doxyfile | 3 ++- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 19242ae..25e743d 100644 --- a/README.md +++ b/README.md @@ -65,3 +65,5 @@ company, Alexey Morozov and Alexey Gromov, for being flexible about my time. For comprehensive information, refer to the documentation (see links at the top of this page) +Feel free to contact me at the Microchip forum, [TNeoKernel thread](http://goo.gl/1xKUwA). + diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 684b721..4581526 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -50,13 +50,15 @@ /* Public functions declared in this file */ + .global __INT0Interrupt .global __tn_arch_context_switch_now_nosave .global __tn_arch_context_switch_pend .global __tn_arch_is_int_disabled .global __tn_arch_inside_isr .global _tn_arch_sr_save_int_dis .global _tn_arch_sr_restore - .global __INT0Interrupt + .global _tn_arch_int_dis + .global _tn_arch_int_en @@ -89,13 +91,9 @@ __tn_arch_context_switch_now_nosave: */ __tn_arch_context_switch_pend: - push w0 - mov #_IFS0, w0 bset [w0], #0 ; IFS0bits.INT0IF = 1 - pop w0 - return @@ -191,14 +189,14 @@ __tn_context_restore: */ _tn_arch_sr_save_int_dis: - push _SR + mov _SR, w1 mov _SR, w0 xor #_TN_IPL_SHIFTED, w0 and #0xE0, w0 xor _SR - pop w0 + mov w1, w0 return @@ -210,8 +208,6 @@ _tn_arch_sr_restore: ; w0 - saved SR - push w1 - mov w0, w1 and #0xE0, w1 mov _SR, w0 @@ -219,10 +215,18 @@ _tn_arch_sr_restore: and #0xE0, w0 xor _SR - pop w1 - return +_tn_arch_int_dis: + + goto _tn_arch_sr_save_int_dis + +_tn_arch_int_en: + + mov #0xff1f, w0 + and _SR + + return /* * See comments for _tn_arch_is_int_disabled() in tn_arch.h diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 5cbaccc..e5351f1 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -38,16 +38,31 @@ #include +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +//-- pointer to interrupt stack TN_UWord *_tn_p24_int_stack_low_addr = TN_NULL; + +//-- pointer to interrupt stack limit (the value to set to SPLIM register) TN_UWord *_tn_p24_int_splim = TN_NULL; +/******************************************************************************* + * ARCHITECTURE-DEPENDENT IMPLEMENTATION + ******************************************************************************/ + +/* + * See comments in the file `tn_arch.h` + */ void _tn_arch_sys_init( TN_UWord *int_stack, unsigned int int_stack_size ) { + //-- set interrupt stack pointers _tn_p24_int_stack_low_addr = int_stack; _tn_p24_int_splim = int_stack + int_stack_size - 1 - 1; @@ -63,6 +78,9 @@ void _tn_arch_sys_init( } +/* + * See comments in the file `tn_arch.h` + */ TN_UWord *_tn_arch_stack_top_get( TN_UWord *stack_low_address, int stack_size @@ -72,6 +90,9 @@ TN_UWord *_tn_arch_stack_top_get( } +/* + * See comments in the file `tn_arch.h` + */ TN_UWord *_tn_arch_stack_init( TN_TaskBody *task_func, TN_UWord *stack_top, @@ -108,19 +129,22 @@ TN_UWord *_tn_arch_stack_init( return stack_top; } +#if 0 +/* + * See comments in the file `tn_arch.h` + */ void tn_arch_int_dis(void) { tn_arch_sr_save_int_dis(); } +/* + * See comments in the file `tn_arch.h` + */ void tn_arch_int_en(void) { //__builtin_enable_interrupts(); //TODO } +#endif - -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- diff --git a/stuff/doxygen/tn_doxyfile b/stuff/doxygen/tn_doxyfile index 9798546..5a5e56b 100644 --- a/stuff/doxygen/tn_doxyfile +++ b/stuff/doxygen/tn_doxyfile @@ -808,7 +808,8 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../../src/tn_cfg.h +EXCLUDE = ../../src/tn_cfg.h \ + ../../src/arch/tn_arch_detect.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded From 6d3066a7fe47da0b1f54b7dac9e3f3e973631923 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 00:54:35 +0300 Subject: [PATCH 56/96] pic24: little refactor --- src/arch/pic24_dspic/tn_arch_pic24.S | 10 +++++++++- src/arch/pic24_dspic/tn_arch_pic24_c.c | 18 ------------------ 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index 4581526..c0dcb28 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -217,14 +217,22 @@ _tn_arch_sr_restore: return + +/* + * See comments for tn_arch_int_dis() in tn_arch.h + */ _tn_arch_int_dis: goto _tn_arch_sr_save_int_dis + +/* + * See comments for tn_arch_int_en() in tn_arch.h + */ _tn_arch_int_en: mov #0xff1f, w0 - and _SR + and _SR, WREG return diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index e5351f1..40f1014 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -129,22 +129,4 @@ TN_UWord *_tn_arch_stack_init( return stack_top; } -#if 0 -/* - * See comments in the file `tn_arch.h` - */ -void tn_arch_int_dis(void) -{ - tn_arch_sr_save_int_dis(); -} - -/* - * See comments in the file `tn_arch.h` - */ -void tn_arch_int_en(void) -{ - //__builtin_enable_interrupts(); - //TODO -} -#endif From f613af10b6852fef1325847ac24445b5705e690a Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 01:05:40 +0300 Subject: [PATCH 57/96] pic24: interrupts documentation improved a bit --- stuff/doc_pages/pic24_details.dox | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/stuff/doc_pages/pic24_details.dox b/stuff/doc_pages/pic24_details.dox index 6ad1fc3..f3f9508 100644 --- a/stuff/doc_pages/pic24_details.dox +++ b/stuff/doc_pages/pic24_details.dox @@ -15,19 +15,15 @@ For detailed information about interrupts in TNeoKernel, refer to the page \ref interrupts. PIC24/dsPIC TNeoKernel port supports nested interrupts. It allows to specify -the range of *system interrupt priorities*; and kernel services are allowed to -call only from interrupts of these priorities. These interrupts will be -referred to as *system interrupts*. - -System interrupts get disabled by the kernel for short periods of time, -when kernel needs to modify critical data. It's about 100 cycles at most. +the range of *system interrupt priorities*. Refer to the section \ref +interrupt_types for details on what is system interrupt. System interrupts use separate interrupt stack instead of the task's stack. This approach saves a lot of RAM. The range is specified by just a single number: `#TN_P24_SYS_IPL`, which -represents maximum *system interrupt priority*. Here is a list of priorities -and their characteristics: +represents maximum *system interrupt priority*. Here is a list of available +priorities and their characteristics: - priorities `[1 .. #TN_P24_SYS_IPL]`: - Kernel services **are** allowed to call; From fb69d6713a3ea0956c5a2808ab09b547d4ab2a68 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 01:09:04 +0300 Subject: [PATCH 58/96] readme updated --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 25e743d..7e0642c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ round-robin scheduling for the tasks with identical priority. TNeoKernel was born as a thorough review and re-implementation of [TNKernel](http://tnkernel.com) v2.7. The new kernel has well-formed code, inherited bugs are fixed as well as new features being added, it is well documented and tested carefully with unit-tests. -Currently it is available for PIC32/PIC24/dsPIC, and it will be ported at least to ARM Cortex M3. +Currently it is available for PIC32 (PIC24/dsPIC is also supported in BETA), and it will be ported at least to ARM Cortex M3. Comprehensive documentation is available in two forms: html and pdf. From bdcd95b097e8c40f81119140d7580b9d72bc4b39 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 01:12:48 +0300 Subject: [PATCH 59/96] changelog: added PIC24/dsPIC --- stuff/doc_pages/changelog.dox | 1 + 1 file changed, 1 insertion(+) diff --git a/stuff/doc_pages/changelog.dox b/stuff/doc_pages/changelog.dox index aa01383..1311fb3 100644 --- a/stuff/doc_pages/changelog.dox +++ b/stuff/doc_pages/changelog.dox @@ -7,6 +7,7 @@ TNeoKernel changelog \section changelog_current Current development version (BETA) + - Added PIC24/dsPIC support, refer to the page \ref pic24_details; - Refactor: the following symbols: `NULL`, `BOOL`, `TRUE`, `FALSE` now have the `TN_` prefix: `#TN_NULL`, `#TN_BOOL`, `#TN_TRUE`, `#TN_FALSE`. This is because non-prefixed symbols may be defined by some other program module, From b0ecc22601b53cb57a1d639b69e73b44fbe244d5 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 01:49:49 +0300 Subject: [PATCH 60/96] added tn_arch_pic24_bfa.h, and BFA() macro is now used to set INT0 priority --- src/arch/pic24_dspic/tn_arch_pic24_bfa.h | 198 +++++++++++++++++++++++ src/arch/pic24_dspic/tn_arch_pic24_c.c | 8 +- 2 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 src/arch/pic24_dspic/tn_arch_pic24_bfa.h diff --git a/src/arch/pic24_dspic/tn_arch_pic24_bfa.h b/src/arch/pic24_dspic/tn_arch_pic24_bfa.h new file mode 100644 index 0000000..a74ddeb --- /dev/null +++ b/src/arch/pic24_dspic/tn_arch_pic24_bfa.h @@ -0,0 +1,198 @@ +/******************************************************************************* + * + * TNeoKernel: real-time kernel initially based on TNKernel + * + * TNKernel: copyright © 2004, 2013 Yuri Tiomkin. + * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen. + * TNeoKernel: copyright © 2014 Dmitry Frank. + * + * TNeoKernel was born as a thorough review and re-implementation of + * TNKernel. The new kernel has well-formed code, inherited bugs are fixed + * as well as new features being added, and it is tested carefully with + * unit-tests. + * + * API is changed somewhat, so it's not 100% compatible with TNKernel, + * hence the new name: TNeoKernel. + * + * Permission to use, copy, modify, and distribute this software in source + * and binary forms and its documentation for any purpose and without fee + * is hereby granted, provided that the above copyright notice appear + * in all copies and that both that copyright notice and this permission + * notice appear in supporting documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/** + * \file + * + * Atomic bit-field access macros. + * + * Author: Alex Borisov, his article in russian could be found here: + * http://www.pic24.ru/doku.php/articles/mchp/c30_atomic_access + * + */ + +#ifndef _TN_ARCH_PIC24_BFA_H +#define _TN_ARCH_PIC24_BFA_H + + + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + + + +#ifdef __cplusplus +extern "C" { /*}*/ +#endif + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +/* Access params */ + +#define BFA_SET 0x1111 +#define BFA_CLR 0x2222 +#define BFA_INV 0x3333 /* invert bit field */ + +#define BFA_WR 0xAAAA /* write bit field */ +#define BFA_RD 0xBBBB /* read bit field */ + +#define __BFA_COMM_ERR(a) __BFA_COMMAND_ERROR_##a +#define __BFA_COMM_GET(a) __BFA_COMM_ERR(a) + +typedef unsigned int __BFA_COMM_GET(BFA_SET); +typedef unsigned int __BFA_COMM_GET(BFA_CLR); +typedef unsigned int __BFA_COMM_GET(BFA_INV); + +typedef unsigned int __BFA_COMM_GET(BFA_WR); +typedef unsigned int __BFA_COMM_GET(BFA_RD); + +#define __BFA_STRUCT_TYPE(a) a##BITS +#define __BFA_STRUCT_VAL(a) a##bits + +/** + * Macro for atomic access to structure field. + * + * comm - command to execute + * - BFA_WR - write bit field + * - BFA_RD - read bit field + * - BFA_SET - set bit fields by mask + * - BFA_CLR - clear bit fields by mask + * - BFA_INV - invert bit fields by mask + * reg_name - register name (PORTA, CMCON, ...). + * field_name - structure field name + * ... - used if only comm = BFA_WR. Should be equal to the value + * to write to field. You can use variable here. + * + * Usage examples: + * BFA(BFA_WR, IPC0, INT0IP, 0); + * BFA(BFA_INV, IPC0, INT0IP, 1); + * a = BFA(BFA_RD, IPC0, INT0IP); + * BFA(BFA_WR, IPC0, INT0IP, a); + * BFA(BFA_SET, IPC0, INT0IP, (1 << 2)); + */ +#define BFA(comm, reg_name, field_name, ...) \ + ({ \ + union \ + { \ + __BFA_STRUCT_TYPE(reg_name) o; \ + unsigned int i; \ + } lcur, lmask={}, lval={}; \ + \ + lmask.o.field_name = -1; \ + \ + ((comm) == BFA_WR) \ + ?({ \ + __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask.i & (lmask.i-1)) \ + { \ + lval.o.field_name = v; \ + lcur.o = __BFA_STRUCT_VAL(reg_name); \ + __asm__ __volatile__ \ + ("xor %0":"=U"(reg_name):"a"(lmask.i & (lval.i^lcur.i))); \ + } \ + else \ + { \ + if (v & 1) \ + { \ + __BFA_STRUCT_VAL(reg_name).field_name = 1; \ + } \ + else \ + { \ + __BFA_STRUCT_VAL(reg_name).field_name = 0; \ + } \ + } \ + }), 0 \ + \ + :(((comm) == BFA_INV) \ + ?({ \ + __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + lval.o.field_name = v; \ + __asm__ __volatile__(" xor %0" \ + :"=U"(reg_name):"a"(lmask.i & lval.i)); \ + }), 0 \ + \ + :((((comm) == BFA_SET) \ + ?({ \ + __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask.i & (lmask.i-1)) \ + { \ + lval.o.field_name = v; \ + __asm__ __volatile__ \ + ("ior %0":"=U"(reg_name):"a"(lmask.i & lval.i)); \ + } \ + else \ + { \ + if (v & 1) \ + __BFA_STRUCT_VAL(reg_name).field_name = 1; \ + } \ + }), 0 \ + \ + :(((((comm) == BFA_CLR) \ + ?({ \ + __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask.i & (lmask.i-1)) \ + { \ + lval.o.field_name = v; \ + __asm__ __volatile__ \ + ("and %0":"=U"(reg_name):"a"(~(lmask.i & lval.i))); \ + } \ + else \ + { \ + if (v & 1) \ + __BFA_STRUCT_VAL(reg_name).field_name = 0; \ + } \ + }), 0 \ + \ + :({ /* BFA_RD */ \ + __BFA_STRUCT_VAL(reg_name).field_name; \ + }))))))); \ + }) + + + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // _TN_ARCH_PIC24_BFA_H + diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 40f1014..cfc2719 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -35,6 +35,7 @@ ******************************************************************************/ #include "tn_tasks.h" +#include "tn_arch_pic24_bfa.h" #include @@ -68,11 +69,8 @@ void _tn_arch_sys_init( //-- set up software interrupt for context switching - - IPC0bits.INT0IP = 1; //-- set lowest interrupt priority - // TODO: this code isn't atomic, but this function - // is called at system startup, so, nobody should - // interfere + BFA(BFA_WR, IPC0, INT0IP, 1); //-- set lowest interrupt priority + // for context switch interrupt IFS0bits.INT0IF = 0; //-- clear interrupt flag IEC0bits.INT0IE = 1; //-- enable interrupt } From b24b4cd2643c407efe12e3549122a896ebdce2b5 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 22:33:07 +0300 Subject: [PATCH 61/96] added _tn_task_exit_nodelete() which takes no arguments, it is needed for returning from task body function to be the same as calling tn_task_exit(). pic24: it is used. --- src/arch/pic24_dspic/tn_arch_pic24.h | 2 +- src/arch/pic24_dspic/tn_arch_pic24_c.c | 4 +++- src/arch/pic32/tn_arch_pic32.c | 4 ++-- src/core/internal/_tn_tasks.h | 8 ++++++++ src/core/tn_tasks.c | 8 ++++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 919aa83..4b8b735 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -120,7 +120,7 @@ extern "C" { /*}*/ * Minimum task's stack size, in words, not in bytes; includes a space for * context plus for parameters passed to task's body function. */ -#define TN_MIN_STACK_SIZE 23 +#define TN_MIN_STACK_SIZE 25 /** * Width of `int` type. diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index cfc2719..2b990ee 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -34,7 +34,7 @@ * ******************************************************************************/ -#include "tn_tasks.h" +#include "_tn_tasks.h" #include "tn_arch_pic24_bfa.h" #include @@ -100,6 +100,8 @@ TN_UWord *_tn_arch_stack_init( { TN_UWord *p_splim = stack_top + stack_size - 1 - 1; + *(stack_top++) = (TN_UWord)_tn_task_exit_nodelete; + *(stack_top++) = 0; *(stack_top++) = (TN_UWord)task_func; *(stack_top++) = 0; *(stack_top++) = 0x0103; // SR diff --git a/src/arch/pic32/tn_arch_pic32.c b/src/arch/pic32/tn_arch_pic32.c index b843e78..7cc4038 100644 --- a/src/arch/pic32/tn_arch_pic32.c +++ b/src/arch/pic32/tn_arch_pic32.c @@ -38,7 +38,7 @@ * INCLUDED FILES ******************************************************************************/ -#include "tn_tasks.h" +#include "_tn_tasks.h" @@ -200,7 +200,7 @@ TN_UWord *_tn_arch_stack_init( *(--stack_top) = 0; *(--stack_top) = (TN_UWord)task_func; //-- EPC *(--stack_top) = 3; //-- Status: EXL and IE bits are set - *(--stack_top) = (TN_UWord)tn_task_exit; //-- ra + *(--stack_top) = (TN_UWord)_tn_task_exit_nodelete; //-- ra *(--stack_top) = 0x30303030L; //-- fp *(--stack_top) = (TN_UWord)&_gp; //-- gp - provided by linker *(--stack_top) = 0x25252525L; //-- t9 diff --git a/src/core/internal/_tn_tasks.h b/src/core/internal/_tn_tasks.h index 4d05316..ed54c3e 100644 --- a/src/core/internal/_tn_tasks.h +++ b/src/core/internal/_tn_tasks.h @@ -368,6 +368,14 @@ TN_BOOL _tn_task_first_wait_complete( ); +/** + * The same as `tn_task_exit(0)`, we need this function that takes no arguments + * for exiting from task body function: we just set up initial task's stack so + * that return address is `#_tn_task_exit_nodelete`, and it works. + * + * If the function takes arguments, it becomes much harder. + */ +void _tn_task_exit_nodelete(void); /******************************************************************************* diff --git a/src/core/tn_tasks.c b/src/core/tn_tasks.c index fc26ab5..0c5f24e 100644 --- a/src/core/tn_tasks.c +++ b/src/core/tn_tasks.c @@ -1156,3 +1156,11 @@ TN_BOOL _tn_is_mutex_locked_by_task(struct TN_Task *task, struct TN_Mutex *mutex #endif +/* + * See comment in the _tn_tasks.h file + */ +void _tn_task_exit_nodelete(void) +{ + tn_task_exit((0)); +} + From ec9fada3fd6add22514269c13768215e1408be4c Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Sun, 2 Nov 2014 23:15:03 +0300 Subject: [PATCH 62/96] improved docs for tasks --- src/core/tn_tasks.h | 73 ++++++++++++++++++++++++++++++++++++++- stuff/doxygen/tn_doxyfile | 5 +-- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/core/tn_tasks.h b/src/core/tn_tasks.h index b5d1bf2..77f6da5 100644 --- a/src/core/tn_tasks.h +++ b/src/core/tn_tasks.h @@ -37,7 +37,75 @@ /** * \file * - * Various task services: create, sleep, wake up, terminate, etc. + * \section tn_tasks__tasks Task + * + * In TNeoKernel, a task is a branch of code that runs concurrently with other + * tasks from the programmer's point of view. Indeed, tasks are actually + * executed using processor time sharing. Each task can be considered to be an + * independed program, which executes in its own context (processor registers, + * stack pointer, etc.). + * + * Actually, the term thread is more accurate than task, but the + * term task historically was used in TNKernel, so TNeoKernel keeps this + * convention. + * + * When kernel decides that it's time to run another task, it performs + * context switch: current context (at least, values of all registers) + * gets saved to the preempted task's stack, pointer to currently running + * task is altered as well as stack pointer, and context gets restored from + * the stack of newly running task. + * + * \section tn_tasks__states Task states + * + * For list of task states and their description, refer to `enum + * #TN_TaskState`. + * + * + * \section tn_tasks__creating Creating/starting tasks + * + * Create task and delete task are two separate actions; although you can + * perform both of them in one step by passing `#TN_TASK_CREATE_OPT_START` flag + * to the `tn_task_create()` function. + * + * \section tn_tasks__stopping Stopping/deleting tasks + * + * Stop task and delete task are two separate actions. If task was just stopped + * but not deleted, it can be just restarted again by calling + * `tn_task_activate()`. If task was deleted, it can't be just activated: it + * should be re-created by `tn_task_create()` first. + * + * Task stops execution when: + * + * - it calls `tn_task_exit()`; + * - it returns from its task body function (it is the equivalent to + * `tn_task_exit(0)`) + * - some other task calls `tn_task_terminate()` passing appropriate pointer to + * `struct #TN_Task`. + * + * \section tn_tasks__scheduling Scheduling rules + * + * TNeoKernel always runs the most privileged task in state + * $(TN_TASK_STATE_RUNNABLE). In no circumstances can task run while there is + * at least one task is in the $(TN_TASK_STATE_RUNNABLE) state with higher + * priority. Task will run until: + * + * - It becomes non-runnable (say, it may wait for something, etc) + * - Some other task with higher priority becomes runnable. + * + * Tasks with the same priority may be scheduled in round robin fashion by + * getting a predetermined time slice for each task with this priority. + * Time slice is set separately for each priority. By default, round robin + * is turned off for all priorities. + * + * \section tn_tasks__idle Idle task + * + * TNeoKernel has one system task: an idle task, which has lowest priority. + * It is always in the state $(TN_TASK_STATE_RUNNABLE), and it runs only when + * there are no other runnable tasks. + * + * User can provide a callback function to be called from idle task, see + * #TN_CBIdle. It is useful to bring the processor to some kind of real idle + * state, so that device draws less current. * */ @@ -589,6 +657,9 @@ enum TN_RCode tn_task_irelease_wait(struct TN_Task *task); * task will be deleted after termination and cannot be reactivated (needs * recreation). * + * Please note that returning from task body function has the same effect as + * calling `tn_task_exit(0)`. + * * $(TN_CALL_FROM_TASK) * $(TN_CAN_SWITCH_CONTEXT) * $(TN_LEGEND_LINK) diff --git a/stuff/doxygen/tn_doxyfile b/stuff/doxygen/tn_doxyfile index 5a5e56b..ea1171d 100644 --- a/stuff/doxygen/tn_doxyfile +++ b/stuff/doxygen/tn_doxyfile @@ -808,8 +808,9 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../../src/tn_cfg.h \ - ../../src/arch/tn_arch_detect.h +EXCLUDE = ../../src/tn_cfg.h \ + ../../src/arch/tn_arch_detect.h \ + ../../src/arch/pic24_dspic/tn_arch_pic24_bfa.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded From 51d39e8dfde3f4639d2dcb2d8c805fb9ecbb78a2 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 00:04:51 +0300 Subject: [PATCH 63/96] pic32: application doesn't need to set CS0 interrupt anymore, this is done by kernel --- src/arch/pic32/tn_arch_pic32.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/arch/pic32/tn_arch_pic32.c b/src/arch/pic32/tn_arch_pic32.c index 7cc4038..ce5ffb3 100644 --- a/src/arch/pic32/tn_arch_pic32.c +++ b/src/arch/pic32/tn_arch_pic32.c @@ -39,6 +39,7 @@ ******************************************************************************/ #include "_tn_tasks.h" +#include @@ -109,6 +110,18 @@ void _tn_arch_sys_init( int_stack, int_stack_size ); + + + //-- setup core software 0 interrupt, it should be set to lowest priority + // and should not use shadow register set. + // (TNKernel-PIC32 port uses it for switch context routine) + + //-- set priority 1 and subpriority 0; + IPC0CLR = 0x00001f00; //-- initially, reset both priority and subp. to 0 + IPC0SET = 0x00000400; //-- then, set priority to 1 + + IFS0CLR = 0x00000002; //-- clear interrupt flag + IEC0SET = 0x00000002; //-- enable interrupt } From cc86dbb9b3862b9e299f55a9187cd033d22d0ec6 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 00:11:23 +0300 Subject: [PATCH 64/96] examples updated --- .../nbproject/configurations.xml | 2 ++ examples/basic/arch/pic32/tn_pic32_example_basic.c | 11 ----------- examples/common/arch/pic32/pic32_arch.c | 11 ----------- .../nbproject/configurations.xml | 2 ++ examples/queue/task_consumer.c | 2 +- examples/queue/task_producer.c | 4 ++-- .../nbproject/configurations.xml | 2 ++ examples/queue_eventgrp_conn/task_consumer.c | 2 +- examples/queue_eventgrp_conn/task_producer.c | 6 +++--- 9 files changed, 13 insertions(+), 29 deletions(-) diff --git a/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml b/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml index 9306e2f..0da1c7f 100644 --- a/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml +++ b/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml @@ -61,6 +61,8 @@ + + false false diff --git a/examples/basic/arch/pic32/tn_pic32_example_basic.c b/examples/basic/arch/pic32/tn_pic32_example_basic.c index 661fafc..464f465 100644 --- a/examples/basic/arch/pic32/tn_pic32_example_basic.c +++ b/examples/basic/arch/pic32/tn_pic32_example_basic.c @@ -191,17 +191,6 @@ void hw_init(void) INTClearFlag(INT_T5); INTEnable(INT_T5, INT_ENABLED); - //-- TNeoKernel PIC32 requirement: - // set up the software interrupt 0 with a priority of 1, subpriority 0 - // - // NOTE: the ISR is declared in kernel-provided file - // tn_arch_pic32_int_vec1.S, which should be included in the application - // project itself, in order to dispatch vector correctly. - INTSetVectorPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_PRIORITY_LEVEL_1); - INTSetVectorSubPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_SUB_PRIORITY_LEVEL_0); - INTClearFlag(INT_CS0); - INTEnable(INT_CS0, INT_ENABLED); - //-- enable multi-vectored interrupt mode INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR); } diff --git a/examples/common/arch/pic32/pic32_arch.c b/examples/common/arch/pic32/pic32_arch.c index ac4ed7c..ec6df96 100644 --- a/examples/common/arch/pic32/pic32_arch.c +++ b/examples/common/arch/pic32/pic32_arch.c @@ -154,17 +154,6 @@ void hw_init(void) INTClearFlag(INT_T5); INTEnable(INT_T5, INT_ENABLED); - //-- TNeoKernel PIC32 requirement: - // set up the software interrupt 0 with a priority of 1, subpriority 0 - // - // NOTE: the ISR is declared in kernel-provided file - // tn_arch_pic32_int_vec1.S, which should be included in the application - // project itself, in order to dispatch vector correctly. - INTSetVectorPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_PRIORITY_LEVEL_1); - INTSetVectorSubPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_SUB_PRIORITY_LEVEL_0); - INTClearFlag(INT_CS0); - INTEnable(INT_CS0, INT_ENABLED); - //-- enable multi-vectored interrupt mode INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR); } diff --git a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml index cd8df9b..c1f0a00 100644 --- a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml +++ b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml @@ -67,6 +67,8 @@ + + false false diff --git a/examples/queue/task_consumer.c b/examples/queue/task_consumer.c index cc5ddd9..6fef06d 100644 --- a/examples/queue/task_consumer.c +++ b/examples/queue/task_consumer.c @@ -174,7 +174,7 @@ void task_consumer_create(void) TASK_CONSUMER_PRIORITY, task_consumer_stack, TASK_CONSUMER_STACK_SIZE, - NULL, + TN_NULL, (TN_TASK_CREATE_OPT_START) ) ); diff --git a/examples/queue/task_producer.c b/examples/queue/task_producer.c index d3c4fcc..d622472 100644 --- a/examples/queue/task_producer.c +++ b/examples/queue/task_producer.c @@ -60,7 +60,7 @@ static void appl_init(void) queue_example_eventgrp_get(), QUE_EXAMPLE_FLAG__TASK_CONSUMER_INIT, TN_EVENTGRP_WMODE_AND, - NULL, + TN_NULL, TN_WAIT_INFINITE ) ); @@ -151,7 +151,7 @@ void task_producer_create(void) TASK_PRODUCER_PRIORITY, task_producer_stack, TASK_PRODUCER_STACK_SIZE, - NULL, + TN_NULL, (TN_TASK_CREATE_OPT_START) ) ); diff --git a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml index 2e8a591..211ccbd 100644 --- a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml +++ b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml @@ -67,6 +67,8 @@ + + false false diff --git a/examples/queue_eventgrp_conn/task_consumer.c b/examples/queue_eventgrp_conn/task_consumer.c index 62720f5..7318507 100644 --- a/examples/queue_eventgrp_conn/task_consumer.c +++ b/examples/queue_eventgrp_conn/task_consumer.c @@ -296,7 +296,7 @@ void task_consumer_create(void) TASK_CONSUMER_PRIORITY, task_consumer_stack, TASK_CONSUMER_STACK_SIZE, - NULL, + TN_NULL, (TN_TASK_CREATE_OPT_START) ) ); diff --git a/examples/queue_eventgrp_conn/task_producer.c b/examples/queue_eventgrp_conn/task_producer.c index 594158f..eba7069 100644 --- a/examples/queue_eventgrp_conn/task_producer.c +++ b/examples/queue_eventgrp_conn/task_producer.c @@ -83,7 +83,7 @@ static void appl_init(void) queue_example_eventgrp_get(), QUE_EXAMPLE_FLAG__TASK_CONSUMER_INIT, TN_EVENTGRP_WMODE_AND, - NULL, + TN_NULL, TN_WAIT_INFINITE ) ); @@ -92,7 +92,7 @@ static void appl_init(void) //-- create and start timer for sending message B {{{ { - tn_timer_create(&my_timer, my_timer_callback, NULL); + tn_timer_create(&my_timer, my_timer_callback, TN_NULL); tn_timer_start(&my_timer, MY_TIMER_PERIOD); } //}}} @@ -184,7 +184,7 @@ void task_producer_create(void) TASK_PRODUCER_PRIORITY, task_producer_stack, TASK_PRODUCER_STACK_SIZE, - NULL, + TN_NULL, (TN_TASK_CREATE_OPT_START) ) ); From 1280bacbfdff4a8c2245f97a278c0fce96b9e9cc Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 00:14:55 +0300 Subject: [PATCH 65/96] pic32: docs updated --- stuff/doc_pages/pic32_details.dox | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/stuff/doc_pages/pic32_details.dox b/stuff/doc_pages/pic32_details.dox index ed2e3f8..bf0d86a 100644 --- a/stuff/doc_pages/pic32_details.dox +++ b/stuff/doc_pages/pic32_details.dox @@ -6,18 +6,14 @@ PIC32 port implementation details \section pic32_context_switch Context switch -The context switch is implemented using the core software 0 interrupt. It -should be configured to use the lowest priority in the system: +The context switch is implemented using the core software 0 interrupt (`CS0`), +which is configured by the kernel to the lowest priority (1). This interrupt is +handled completely by the kernel, application should never touch it. -\code{.c} -// set up the software interrupt 0 with a priority of 1, subpriority 0 -INTSetVectorPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_PRIORITY_LEVEL_1); -INTSetVectorSubPriority(INT_CORE_SOFTWARE_0_VECTOR, INT_SUB_PRIORITY_LEVEL_0); -INTEnable(INT_CS0, INT_ENABLED); -\endcode +The interrupt priority level 1 should not be configured to use shadow register +sets. -The interrupt priority level used by the context switch interrupt should not be -configured to use shadow register sets. +Multi-vectored interrupt mode should be enabled. \attention if tneokernel is built as a separate library, then the file `src/arch/pic32/tn_arch_pic32_int_vec1.S` must be included in the main project From 511f263b355dee00337c84656e9d0854ce96e52d Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 00:54:49 +0300 Subject: [PATCH 66/96] pic24 example basic cleaned up somewhat --- .../nbproject/configurations.xml | 14 +-- .../nbproject/project.xml | 2 +- .../basic/arch/pic24/tn_pic24_example_basic.c | 117 ++++-------------- 3 files changed, 33 insertions(+), 100 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml index e2efc73..c0f5dbb 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml @@ -43,20 +43,20 @@ - + OP="dist/default/production/tneokernel_pic24_dspic.X.a" + DOP="dist/default/debug/tneokernel_pic24_dspic.X.a" + FL="dist/default/production/tneokernel_pic24_dspic.X.a" + PD="dist/default/production/tneokernel_pic24_dspic.X." + DD="dist/default/debug/tneokernel_pic24_dspic.X."> diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml index 7cfa814..64f9eab 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/project.xml @@ -11,7 +11,7 @@ UTF-8 - ../../../../../src/arch/pic24_dspic/tneokernel_pic24.X + ../../../../../src/arch/pic24_dspic/tneokernel_pic24_dspic.X diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index 05385b8..c282e7c 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -176,34 +176,22 @@ // }}} -//#pragma config CONFIG1H = 0x08; -__CSP_CONFIG_1(JTAG_DIS | /* JTAG disabled */ -#if defined(__DEBUG) +__CSP_CONFIG_1( + JTAG_DIS | /* JTAG disabled */ CODE_PROTECT_DIS | /* Code Protect disabled */ -#else - CODE_PROTECT_EN | /* TODO:change Code Protect enabled */ -#endif CODE_WRITE_EN | /* Code write enabled */ -#if defined(__DEBUG) BACKGROUND_DEBUG_EN | /* Debug enabled */ EMULATION_EN | /* Emulation enabled */ -#else - BACKGROUND_DEBUG_DIS | /* Debug enabled */ - EMULATION_DIS | /* Emulation enabled */ -#endif ICD_PIN_PGX2 | /* PGC2/PGD2 pins used for debug */ -#if defined(__DEBUG) WDT_DIS | /* WDT disabled */ -#else - WDT_DIS | /* WDT disabled */ -#endif WDT_WINDOW_DIS | /* WDT mode is not-windowed */ -WDT_PRESCALE_32 | /* WDT prescale is 1:32 */ -WDT_POSTSCALE_1 /* WDT postscale is 1:1 */ -); + WDT_PRESCALE_32 | /* WDT prescale is 1:32 */ + WDT_POSTSCALE_1 /* WDT postscale is 1:1 */ + ); -__CSP_CONFIG_2(TWO_SPEED_STARTUP_DIS | /* Two-speed startup disabled */ +__CSP_CONFIG_2( + TWO_SPEED_STARTUP_DIS | /* Two-speed startup disabled */ USB_PLL_PRESCALE_4 | OSC_STARTUP_PRIMARY_PLL | /* Startup oscillator is Primary with PLL */ CLK_SW_DIS_CLK_MON_DIS | /* Clock switch disabled, monitor disabled */ @@ -213,7 +201,8 @@ __CSP_CONFIG_2(TWO_SPEED_STARTUP_DIS | /* Two-speed startup disabled PRIMARY_OSC_HS /* Primary oscillator mode is HS */ ); -__CSP_CONFIG_3(CODE_WRITE_PROT_MEM_START | /* Code write protect block from start */ +__CSP_CONFIG_3( + CODE_WRITE_PROT_MEM_START | /* Code write protect block from start */ CODE_WRITE_CONF_MEM_DIS | /* Code config memory block not protected */ CODE_WRITE_BLOCK_DIS /* Code block protect disabled */ ); @@ -247,7 +236,7 @@ __CSP_CONFIG_3(CODE_WRITE_PROT_MEM_START | /* Code write protect block from //-- idle task stack size, in words -#define IDLE_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 16 + 100/*TODO: remove*/) +#define IDLE_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 16) //-- interrupt stack size, in words #define INTERRUPT_STACK_SIZE (TN_MIN_STACK_SIZE + 64) @@ -298,15 +287,10 @@ struct TN_Task task_c = {}; /** * system timer ISR */ -//tn_soft_isr(_TIMER_5_VECTOR) -void __attribute__((__interrupt__, auto_psv)) _T1Interrupt(void) +tn_p24_soft_isr(_T1Interrupt, auto_psv) { IFS0bits.T1IF = 0; - volatile int b; - b = 1; - b = _tn_arch_is_int_disabled(); - b = 1; tn_tick_int_processing(); } @@ -328,9 +312,8 @@ void task_a_body(void *par) // (job for which task was created at all) for(;;) { - //mPORTEToggleBits(BIT_0); - LATE ^= (1 << 0); - tn_task_sleep(50); + __builtin_btg(&LATE, 0); + tn_task_sleep(500); } } @@ -338,9 +321,8 @@ void task_b_body(void *par) { for(;;) { - //mPORTEToggleBits(BIT_1); - LATE ^= (1 << 1); - tn_task_sleep(100); + __builtin_btg(&LATE, 1); + tn_task_sleep(1000); } } @@ -348,9 +330,8 @@ void task_c_body(void *par) { for(;;) { - //mPORTEToggleBits(BIT_2); - LATE ^= (1 << 2); - tn_task_sleep(150); + __builtin_btg(&LATE, 2); + tn_task_sleep(1500); } } @@ -359,12 +340,7 @@ void task_c_body(void *par) */ void hw_init(void) { - //SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); - - //turn off ADC function for all pins - //AD1PCFG = 0xffffffff; - - //-- enable timer5 interrupt + //-- set up timer1 T1CONbits.TCS = 0; T1CONbits.TGATE = 0; T1CONbits.TSIDL = 1; @@ -376,9 +352,6 @@ void hw_init(void) IEC0bits.T1IE = 1; IPC0bits.T1IP = 2; T1CONbits.TON = 1; - - IEC0bits.INT0IE = 1; - IPC0bits.INT0IP = 1; } /** @@ -387,8 +360,6 @@ void hw_init(void) void appl_init(void) { //-- configure LED port pins - //mPORTESetPinsDigitalOut(BIT_0 | BIT_1 | BIT_2); - //mPORTEClearBits(BIT_0 | BIT_1 | BIT_2); TRISEbits.TRISE0 = 0; TRISEbits.TRISE1 = 0; @@ -403,14 +374,13 @@ void appl_init(void) //-- create all the rest application tasks -#if 1 tn_task_create( &task_b, task_b_body, TASK_B_PRIORITY, task_b_stack, TASK_B_STK_SIZE, - NULL, + TN_NULL, (TN_TASK_CREATE_OPT_START) ); @@ -420,10 +390,9 @@ void appl_init(void) TASK_C_PRIORITY, task_c_stack, TASK_C_STK_SIZE, - NULL, + TN_NULL, (TN_TASK_CREATE_OPT_START) ); -#endif } //-- idle callback that is called periodically from idle task @@ -436,49 +405,26 @@ void init_task_create(void) { //-- task A performs complete application initialization, // it's the first created application task -#if 1 tn_task_create( &task_a, //-- task structure task_a_body, //-- task body function TASK_A_PRIORITY, //-- task priority task_a_stack, //-- task stack TASK_A_STK_SIZE, //-- task stack size (in words) - NULL, //-- task function parameter + TN_NULL, //-- task function parameter TN_TASK_CREATE_OPT_START //-- creation option ); -#endif } int main(void) { -#ifndef PIC32_STARTER_KIT - /*The JTAG is on by default on POR. A PIC32 Starter Kit uses the JTAG, but - for other debug tool use, like ICD 3 and Real ICE, the JTAG should be off - to free up the JTAG I/O */ - //DDPCONbits.JTAGEN = 0; -#endif - -#if 1 - //-- unconditionally disable interrupts + //-- unconditionally disable system interrupts tn_arch_int_dis(); -#endif //-- init hardware hw_init(); -#if 0 - for (;;){ - volatile int i; - i++; - if (i > 10){ - i = 0; - IFS1bits.INT1IF = 1; - } - } -#endif - -#if 1 //-- call to tn_sys_start() never returns tn_sys_start( idle_task_stack, @@ -488,7 +434,6 @@ int main(void) init_task_create, idle_task_callback ); -#endif //-- unreachable return 1; @@ -504,40 +449,28 @@ void __attribute((__interrupt__, auto_psv)) _AddressError (void) //for(;;); } -/** - * - */ void __attribute((__interrupt__, auto_psv)) _StackError (void) { PIC24_SOFTWARE_BREAK(); - // for(;;); + //for(;;); } -/** - * - */ void __attribute((__interrupt__, auto_psv)) _MathError (void) { PIC24_SOFTWARE_BREAK(); //for(;;); } -/** - * - */ void __attribute((__interrupt__, auto_psv)) _OscillatorFail (void) { PIC24_SOFTWARE_BREAK(); //for(;;); } -/** - * - * - * - */ void __attribute((__interrupt__, auto_psv)) _DefaultInterrupt (void) { PIC24_SOFTWARE_BREAK(); //for(;;); } + + From 3fc0f0cbbe53794ed99c5d6dd460fce81c60acfc Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 01:57:24 +0300 Subject: [PATCH 67/96] added TN_UIntPtr (as analogue of uintptr_t), it is used in tn_fmem.c. pic24: basic exampleuses XC16 instead of C30 --- .../tn_pic24_example_basic.X/nbproject/configurations.xml | 8 +++++--- src/.vimprj/my.vim | 2 +- src/arch/pic24_dspic/tn_arch_pic24.h | 7 +++++++ src/arch/pic32/tn_arch_pic32.h | 6 ++++++ src/core/tn_fmem.c | 6 +++--- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml index c0f5dbb..3bcc997 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml @@ -35,8 +35,8 @@ ICD3PlatformTool - C30 - 3_30 + XC16 + 1.21 2 @@ -100,6 +100,9 @@ + + + @@ -200,7 +203,6 @@ - diff --git a/src/.vimprj/my.vim b/src/.vimprj/my.vim index 57f1fae..e82995b 100644 --- a/src/.vimprj/my.vim +++ b/src/.vimprj/my.vim @@ -1,5 +1,5 @@ -" определÑем путь к папке .vim +" detect path to .vimprj dir let s:sPath = expand(':p:h') let g:proj_project_filename=s:sPath.'/.vimprojects' diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 4b8b735..05d1888 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -133,6 +133,13 @@ extern "C" { /*}*/ */ typedef unsigned int TN_UWord; +/** + * Unsigned integer type that is able to store pointers. + * We need it because some platforms don't define `uintptr_t`. + * Typically it's `unsigned int`. + */ +typedef unsigned int TN_UIntPtr; + /** * Maximum number of priorities available, this value usually matches diff --git a/src/arch/pic32/tn_arch_pic32.h b/src/arch/pic32/tn_arch_pic32.h index 5820d80..0163c83 100644 --- a/src/arch/pic32/tn_arch_pic32.h +++ b/src/arch/pic32/tn_arch_pic32.h @@ -164,6 +164,12 @@ extern void *tn_p32_int_sp; */ typedef unsigned int TN_UWord; +/** + * Unsigned integer type that is able to store pointers. + * We need it because some platforms don't define `uintptr_t`. + * Typically it's `unsigned int`. + */ +typedef unsigned int TN_UIntPtr; /** * Maximum number of priorities available, this value usually matches diff --git a/src/core/tn_fmem.c b/src/core/tn_fmem.c index 734f921..8c7be0d 100644 --- a/src/core/tn_fmem.c +++ b/src/core/tn_fmem.c @@ -214,10 +214,10 @@ enum TN_RCode tn_fmem_create( //-- check that start_addr is aligned properly { - unsigned long start_addr_aligned - = TN_MAKE_ALIG_SIZE((unsigned long)start_addr); + TN_UIntPtr start_addr_aligned + = TN_MAKE_ALIG_SIZE((TN_UIntPtr)start_addr); - if (start_addr_aligned != (unsigned int)start_addr){ + if (start_addr_aligned != (TN_UIntPtr)start_addr){ rc = TN_RC_WPARAM; goto out; } From 9907cac19412e75ab9d8f7b341f5e00ceb407d0d Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 02:02:23 +0300 Subject: [PATCH 68/96] changelog updated --- stuff/doc_pages/changelog.dox | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stuff/doc_pages/changelog.dox b/stuff/doc_pages/changelog.dox index 1311fb3..639f5c2 100644 --- a/stuff/doc_pages/changelog.dox +++ b/stuff/doc_pages/changelog.dox @@ -8,6 +8,9 @@ TNeoKernel changelog \section changelog_current Current development version (BETA) - Added PIC24/dsPIC support, refer to the page \ref pic24_details; + - PIC32: Core Software Interrupt is now handled by the kernel completely, + application shouldn't set it up anymore. Refer to the page \ref + pic32_details. - Refactor: the following symbols: `NULL`, `BOOL`, `TRUE`, `FALSE` now have the `TN_` prefix: `#TN_NULL`, `#TN_BOOL`, `#TN_TRUE`, `#TN_FALSE`. This is because non-prefixed symbols may be defined by some other program module, From c213280e84e47cc8132478de68bad21e656ee4a9 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 02:10:34 +0300 Subject: [PATCH 69/96] pic24: arch-dependent code comments improved --- src/arch/pic24_dspic/tn_arch_pic24_c.c | 63 ++++++++++++++++---------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 2b990ee..9257ec7 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -63,7 +63,9 @@ void _tn_arch_sys_init( unsigned int int_stack_size ) { - //-- set interrupt stack pointers + //-- set interrupt stack pointers. + // We need to subtract additional 1 from SPLIM because + // PIC24/dsPIC hardware works this way. _tn_p24_int_stack_low_addr = int_stack; _tn_p24_int_splim = int_stack + int_stack_size - 1 - 1; @@ -71,8 +73,8 @@ void _tn_arch_sys_init( //-- set up software interrupt for context switching BFA(BFA_WR, IPC0, INT0IP, 1); //-- set lowest interrupt priority // for context switch interrupt - IFS0bits.INT0IF = 0; //-- clear interrupt flag - IEC0bits.INT0IE = 1; //-- enable interrupt + BFA(BFA_WR, IFS0, INT0IF, 0); //-- clear interrupt flag + BFA(BFA_WR, IEC0, INT0IE, 1); //-- enable interrupt } @@ -84,6 +86,8 @@ TN_UWord *_tn_arch_stack_top_get( int stack_size ) { + //-- on PIC24/dsPIC, stack grows from low address to high address, + // so, we return low address here. return stack_low_address; } @@ -98,33 +102,44 @@ TN_UWord *_tn_arch_stack_init( void *param ) { + //-- calculate stack pointer limit: we need to subtract additional 1 from + // it because PIC24/dsPIC hardware works this way. TN_UWord *p_splim = stack_top + stack_size - 1 - 1; + //-- set return address that is used when task body function returned: + // we set it to _tn_task_exit_nodelete, so that returning from task + // body function is equivalent to calling tn_task_exit(0) *(stack_top++) = (TN_UWord)_tn_task_exit_nodelete; *(stack_top++) = 0; + + //-- set return address that is used when context is switched to the task + // for the first time. We set it to the task body function. *(stack_top++) = (TN_UWord)task_func; *(stack_top++) = 0; - *(stack_top++) = 0x0103; // SR - *(stack_top++) = 0x1414; // W14 - *(stack_top++) = 0x1212; // W12 - *(stack_top++) = 0x1313; // W13 - *(stack_top++) = 0x1010; // W10 - *(stack_top++) = 0x1111; // W11 - *(stack_top++) = 0x0808; // W08 - *(stack_top++) = 0x0909; // W09 - *(stack_top++) = 0x0606; // W06 - *(stack_top++) = 0x0707; // W07 - *(stack_top++) = 0x0404; // W04 - *(stack_top++) = 0x0505; // W05 - *(stack_top++) = 0x0202; // W02 - *(stack_top++) = 0x0303; // W03 - *(stack_top++) = (TN_UWord)param; // W00 - task func param - *(stack_top++) = 0x0101; // W01 - *(stack_top++) = 0; // RCOUNT - *(stack_top++) = 0; // TBLPAG - *(stack_top++) = 0x04; // CORCON TODO: take from real CORCON value - *(stack_top++) = 0; // PSVPAG - *(stack_top++) = (TN_UWord)p_splim; // SPLIM + + //-- save usual context for PIC24/dsPIC. + *(stack_top++) = 0x0103; // SR + *(stack_top++) = 0x1414; // W14 + *(stack_top++) = 0x1212; // W12 + *(stack_top++) = 0x1313; // W13 + *(stack_top++) = 0x1010; // W10 + *(stack_top++) = 0x1111; // W11 + *(stack_top++) = 0x0808; // W08 + *(stack_top++) = 0x0909; // W09 + *(stack_top++) = 0x0606; // W06 + *(stack_top++) = 0x0707; // W07 + *(stack_top++) = 0x0404; // W04 + *(stack_top++) = 0x0505; // W05 + *(stack_top++) = 0x0202; // W02 + *(stack_top++) = 0x0303; // W03 + *(stack_top++) = (TN_UWord)param; // W00 - task func param + *(stack_top++) = 0x0101; // W01 + *(stack_top++) = 0; // RCOUNT + *(stack_top++) = 0; // TBLPAG + *(stack_top++) = 0x04; // CORCON + // TODO: take from real CORCON value + *(stack_top++) = 0; // PSVPAG + *(stack_top++) = (TN_UWord)p_splim; // SPLIM return stack_top; } From aa0b9b8b2b77b251f79a185611ec61ee7e3d4b15 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 02:19:09 +0300 Subject: [PATCH 70/96] pic32: arch-dependent code comments improved --- src/arch/pic24_dspic/tn_arch_pic24_c.c | 2 +- src/arch/pic32/tn_arch_pic32.c | 181 ++++++++++++++----------- 2 files changed, 103 insertions(+), 80 deletions(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 9257ec7..38268a2 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -106,7 +106,7 @@ TN_UWord *_tn_arch_stack_init( // it because PIC24/dsPIC hardware works this way. TN_UWord *p_splim = stack_top + stack_size - 1 - 1; - //-- set return address that is used when task body function returned: + //-- set return address that is used when task body function returns: // we set it to _tn_task_exit_nodelete, so that returning from task // body function is equivalent to calling tn_task_exit(0) *(stack_top++) = (TN_UWord)_tn_task_exit_nodelete; diff --git a/src/arch/pic32/tn_arch_pic32.c b/src/arch/pic32/tn_arch_pic32.c index ce5ffb3..6b00b9d 100644 --- a/src/arch/pic32/tn_arch_pic32.c +++ b/src/arch/pic32/tn_arch_pic32.c @@ -34,6 +34,43 @@ * ******************************************************************************/ +/* + * PIC32 context layout: + * + * SP + 7C EPC + * SP + 78 Status + * SP + 74 r31/ra + * SP + 70 r30/s8/fp + * SP + 6C r28/gp + * SP + 68 r25/t9 + * SP + 64 r24/t8 + * SP + 60 r23/s7 + * SP + 5C r22/s6 + * SP + 58 r21/s5 + * SP + 54 r20/s4 + * SP + 50 r19/s3 + * SP + 4C r18/s2 + * SP + 48 r17/s1 + * SP + 44 r16/s0 + * SP + 40 r15/t7 + * SP + 3C r14/t6 + * SP + 38 r13/t5 + * SP + 34 r12/t4 + * SP + 30 r11/t3 + * SP + 2C r10/t2 + * SP + 28 r9/t1 + * SP + 24 r8/t0 + * SP + 20 r7/a3 + * SP + 1C r6/a2 + * SP + 18 r5/a1 + * SP + 14 r4/a0 + * SP + 10 r3/v1 + * SP + 0C r2/v0 + * SP + 08 r1/at + * SP + 04 hi + * SP + 00 lo + */ + /******************************************************************************* * INCLUDED FILES ******************************************************************************/ @@ -47,6 +84,7 @@ * EXTERNAL DATA ******************************************************************************/ +//-- gp: provided by linker extern unsigned long _gp; @@ -127,63 +165,27 @@ void _tn_arch_sys_init( -//---------------------------------------------------------------------------- -// Context layout -// -// SP + 7C EPC -// SP + 78 Status -// SP + 74 r31/ra -// SP + 70 r30/s8/fp -// SP + 6C r28/gp -// SP + 68 r25/t9 -// SP + 64 r24/t8 -// SP + 60 r23/s7 -// SP + 5C r22/s6 -// SP + 58 r21/s5 -// SP + 54 r20/s4 -// SP + 50 r19/s3 -// SP + 4C r18/s2 -// SP + 48 r17/s1 -// SP + 44 r16/s0 -// SP + 40 r15/t7 -// SP + 3C r14/t6 -// SP + 38 r13/t5 -// SP + 34 r12/t4 -// SP + 30 r11/t3 -// SP + 2C r10/t2 -// SP + 28 r9/t1 -// SP + 24 r8/t0 -// SP + 20 r7/a3 -// SP + 1C r6/a2 -// SP + 18 r5/a1 -// SP + 14 r4/a0 -// SP + 10 r3/v1 -// SP + 0C r2/v0 -// SP + 08 r1/at -// SP + 04 hi -// SP + 00 lo -//---------------------------------------------------------------------------- - /* * See comments in the `tn_arch.h` file - * - * **NOTE** that returned *top of the stack* is NOT the address which may be - * used for storing the new data. Instead, it is the *previous* address. - * */ TN_UWord *_tn_arch_stack_top_get( TN_UWord *stack_low_address, int stack_size ) { + //-- on MIPS, stack grows from high address to low address, so, + // we return highest stack address plus one. + // + // **NOTE** that returned *top of the stack* is NOT the address which may + // be used for storing the new data. Instead, it is the *previous* + // address. return stack_low_address + stack_size; } -//---------------------------------------------------------------------------- -// Processor specific routine - here for MIPS4K -// -// sizeof(void*) = sizeof(int) -//---------------------------------------------------------------------------- + +/* + * See comments in the file `tn_arch.h` + */ TN_UWord *_tn_arch_stack_init( TN_TaskBody *task_func, TN_UWord *stack_top, @@ -207,51 +209,72 @@ TN_UWord *_tn_arch_stack_init( //-- filling register's position in the stack - for debugging only - *(--stack_top) = 0; //-- ABI argument area + + //-- ABI argument area + *(--stack_top) = 0; *(--stack_top) = 0; *(--stack_top) = 0; *(--stack_top) = 0; - *(--stack_top) = (TN_UWord)task_func; //-- EPC - *(--stack_top) = 3; //-- Status: EXL and IE bits are set - *(--stack_top) = (TN_UWord)_tn_task_exit_nodelete; //-- ra - *(--stack_top) = 0x30303030L; //-- fp - *(--stack_top) = (TN_UWord)&_gp; //-- gp - provided by linker - *(--stack_top) = 0x25252525L; //-- t9 - *(--stack_top) = 0x24242424L; //-- t8 - *(--stack_top) = 0x23232323L; //-- s7 - *(--stack_top) = 0x22222222L; //-- s6 - *(--stack_top) = 0x21212121L; //-- s5 - *(--stack_top) = 0x20202020L; //-- s4 - *(--stack_top) = 0x19191919L; //-- s3 - *(--stack_top) = 0x18181818L; //-- s2 - *(--stack_top) = 0x17171717L; //-- s1 - *(--stack_top) = 0x16161616L; //-- s0 - *(--stack_top) = 0x15151515L; //-- t7 - *(--stack_top) = 0x14141414L; //-- t6 - *(--stack_top) = 0x13131313L; //-- t5 - *(--stack_top) = 0x12121212L; //-- t4 - *(--stack_top) = 0x11111111L; //-- t3 - *(--stack_top) = 0x10101010L; //-- t2 - *(--stack_top) = 0x09090909L; //-- t1 - *(--stack_top) = 0x08080808L; //-- t0 - *(--stack_top) = 0x07070707L; //-- a3 - *(--stack_top) = 0x06060606L; //-- a2 - *(--stack_top) = 0x05050505L; //-- a1 - *(--stack_top) = (TN_UWord)param; //-- a0 - task's function argument - *(--stack_top) = 0x03030303L; //-- v1 - *(--stack_top) = 0x02020202L; //-- v0 - *(--stack_top) = 0x01010101L; //-- at - *(--stack_top) = 0x33333333L; //-- hi - *(--stack_top) = 0x32323232L; //-- lo + + //-- EPC: address that PC is set to when context switch is done + // and `eret` is executed. + // We should set it to task body function address. + *(--stack_top) = (TN_UWord)task_func; + + //-- Status register: EXL and IE bits are set + *(--stack_top) = 0x00000003L; + + //-- Return address that is used when task body function returns: + // we set it to _tn_task_exit_nodelete, so that returning from task + // body function is equivalent to calling tn_task_exit(0) + *(--stack_top) = (TN_UWord)_tn_task_exit_nodelete; + + *(--stack_top) = 0x30303030L; //-- fp + *(--stack_top) = (TN_UWord)&_gp; //-- gp - provided by linker + *(--stack_top) = 0x25252525L; //-- t9 + *(--stack_top) = 0x24242424L; //-- t8 + *(--stack_top) = 0x23232323L; //-- s7 + *(--stack_top) = 0x22222222L; //-- s6 + *(--stack_top) = 0x21212121L; //-- s5 + *(--stack_top) = 0x20202020L; //-- s4 + *(--stack_top) = 0x19191919L; //-- s3 + *(--stack_top) = 0x18181818L; //-- s2 + *(--stack_top) = 0x17171717L; //-- s1 + *(--stack_top) = 0x16161616L; //-- s0 + *(--stack_top) = 0x15151515L; //-- t7 + *(--stack_top) = 0x14141414L; //-- t6 + *(--stack_top) = 0x13131313L; //-- t5 + *(--stack_top) = 0x12121212L; //-- t4 + *(--stack_top) = 0x11111111L; //-- t3 + *(--stack_top) = 0x10101010L; //-- t2 + *(--stack_top) = 0x09090909L; //-- t1 + *(--stack_top) = 0x08080808L; //-- t0 + *(--stack_top) = 0x07070707L; //-- a3 + *(--stack_top) = 0x06060606L; //-- a2 + *(--stack_top) = 0x05050505L; //-- a1 + *(--stack_top) = (TN_UWord)param; //-- a0 - task's function argument + *(--stack_top) = 0x03030303L; //-- v1 + *(--stack_top) = 0x02020202L; //-- v0 + *(--stack_top) = 0x01010101L; //-- at + *(--stack_top) = 0x33333333L; //-- hi + *(--stack_top) = 0x32323232L; //-- lo return stack_top; } + +/* + * See comments in the file `tn_arch.h` + */ void tn_arch_int_dis(void) { __builtin_disable_interrupts(); } + +/* + * See comments in the file `tn_arch.h` + */ void tn_arch_int_en(void) { __builtin_enable_interrupts(); From ce9d4976568265d693a395fff3e231bd75aba880 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 02:20:03 +0300 Subject: [PATCH 71/96] tn_arch_example updated: added TN_UIntPtr there --- src/arch/example/tn_arch_example.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/arch/example/tn_arch_example.h b/src/arch/example/tn_arch_example.h index a44473b..64e1c1e 100644 --- a/src/arch/example/tn_arch_example.h +++ b/src/arch/example/tn_arch_example.h @@ -103,6 +103,13 @@ */ typedef unsigned int TN_UWord; +/** + * Unsigned integer type that is able to store pointers. + * We need it because some platforms don't define `uintptr_t`. + * Typically it's `unsigned int`. + */ +typedef unsigned int TN_UIntPtr; + /** * Maximum number of priorities available, this value usually matches * `#TN_INT_WIDTH`. From 3071edce758d455d02ed742ad05b7e3e24650f2e Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 02:25:27 +0300 Subject: [PATCH 72/96] unit_tests docs: added section 'Tested CPUs' --- stuff/doc_pages/unit_tests.dox | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/stuff/doc_pages/unit_tests.dox b/stuff/doc_pages/unit_tests.dox index b7b5b44..95d610e 100644 --- a/stuff/doc_pages/unit_tests.dox +++ b/stuff/doc_pages/unit_tests.dox @@ -3,6 +3,13 @@ Brief information on the implementation of unit tests +\section tested_cpus Tested CPUs + +Currently, unit tests project is tested in the hardware on the following CPUs: + +- PIC32MX440F512H +- PIC24FJ256GB106 + \section how_tests_are_implemented How tests are implemented Briefly: there is a high-priority task like "test director", which creates From 88c16e0bee9ebeb5bce10f7a08a786ed425a5a3b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 03:02:46 +0300 Subject: [PATCH 73/96] added support of PIC24E and other chips with extended data space (not tested yet) --- src/arch/pic24_dspic/tn_arch_pic24.S | 14 ++++++++++++++ src/arch/pic24_dspic/tn_arch_pic24.h | 14 +++++++++++++- src/arch/pic24_dspic/tn_arch_pic24_c.c | 6 ++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index c0dcb28..fbdb737 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -118,7 +118,14 @@ __INT0Interrupt: push _RCOUNT push _TBLPAG push _CORCON + + .ifdef __HAS_EDS + push _DSRPAG + push _DSWPAG + .else push _PSVPAG + .endif + push _SPLIM /* store sp in preemted task's TCB */ @@ -167,7 +174,14 @@ __tn_context_restore: ; Restore context on stack pointer pop _SPLIM + + .ifdef __HAS_EDS + pop _DSWPAG + pop _DSRPAG + .else pop _PSVPAG + .endif + pop _CORCON pop _TBLPAG pop _RCOUNT diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 05d1888..9fb0af0 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -120,7 +120,19 @@ extern "C" { /*}*/ * Minimum task's stack size, in words, not in bytes; includes a space for * context plus for parameters passed to task's body function. */ -#define TN_MIN_STACK_SIZE 25 +#define TN_MIN_STACK_SIZE (25 + _TN_EDS_STACK_ADD) + +/** + * Some devices have two registers: DSRPAG and DSWPAG instead of PSVPAG. + * If __HAS_EDS__ is defined, device has two these registers, + * so we should take this in account. + */ +#ifdef __HAS_EDS__ +# define _TN_EDS_STACK_ADD 1 +#else +# define _TN_EDS_STACK_ADD 0 +#endif + /** * Width of `int` type. diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index 38268a2..da8819a 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -138,7 +138,13 @@ TN_UWord *_tn_arch_stack_init( *(stack_top++) = 0; // TBLPAG *(stack_top++) = 0x04; // CORCON // TODO: take from real CORCON value +#ifdef __HAS_EDS__ + *(stack_top++) = 0; // DSRPAG + *(stack_top++) = 0; // DSWPAG +#else *(stack_top++) = 0; // PSVPAG +#endif + *(stack_top++) = (TN_UWord)p_splim; // SPLIM return stack_top; From aab42b4a90fc7ec530ef7e06a98cd14d50758ec2 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 03:26:05 +0300 Subject: [PATCH 74/96] pic24 basic example: use instead of 'p24Fxxxx.h' --- examples/basic/arch/pic24/tn_pic24_example_basic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index c282e7c..fb58ff4 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -6,7 +6,7 @@ * INCLUDED FILES ******************************************************************************/ -#include "p24Fxxxx.h" +#include #include "tn.h" From ae06871107bf4704c8712a4d151e38d6e06125f7 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 15:00:22 +0300 Subject: [PATCH 75/96] vimprj name changed: tnkernel_df -> tneokernel --- src/.vimprj/.indexer_files | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/.vimprj/.indexer_files b/src/.vimprj/.indexer_files index 8e7dc33..ef7b3aa 100644 --- a/src/.vimprj/.indexer_files +++ b/src/.vimprj/.indexer_files @@ -1,5 +1,5 @@ -[tnkernel_df] +[tneokernel] $INDEXER_PROJECT_ROOT From fe95eb896b7a1415a57feb89f33ca727ebd08854 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 15:49:44 +0300 Subject: [PATCH 76/96] dqueue: little fix in docs --- src/core/tn_dqueue.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/tn_dqueue.h b/src/core/tn_dqueue.h index 58a8270..439a863 100644 --- a/src/core/tn_dqueue.h +++ b/src/core/tn_dqueue.h @@ -167,7 +167,7 @@ struct TN_DQueueTaskWait { * * @param dque pointer to already allocated struct TN_DQueue. * @param data_fifo pointer to already allocated array of `void *` to store - * data queue items. Can be TN_NULL. + * data queue items. Can be `#TN_NULL`. * @param items_cnt capacity of queue * (count of elements in the `data_fifo` array) * Can be 0. @@ -188,7 +188,7 @@ enum TN_RCode tn_queue_create( * Destruct data queue. * * All tasks that wait for writing to or reading from the queue become - * runnable with `#TN_RC_DELETED` code returned. TN_RCode, struct TN_Task. + * runnable with `#TN_RC_DELETED` code returned. * * $(TN_CALL_FROM_TASK) * $(TN_CAN_SWITCH_CONTEXT) From dcd7944ae94f3276a5705766b89eb5e48f224aa7 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 17:04:51 +0300 Subject: [PATCH 77/96] pic24: XC16 v1.21 -> XC16 v1.23 --- .../tneokernel_pic24_dspic.X/nbproject/configurations.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml index 55162b1..abeb0e6 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml @@ -48,7 +48,7 @@ ICD3PlatformTool XC16 - 1.21 + 1.23 2 From 461dab8a2d8c6878804c2945c6273ea8c18c2c35 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 18:31:53 +0300 Subject: [PATCH 78/96] pic32 MPLABX project renamed: tneokernel.X -> tneokernel_pic32.X --- src/arch/pic32/{tneokernel.X => tneokernel_pic32.X}/Makefile | 0 .../nbproject/configurations.xml | 0 .../nbproject/project.properties | 0 .../{tneokernel.X => tneokernel_pic32.X}/nbproject/project.xml | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename src/arch/pic32/{tneokernel.X => tneokernel_pic32.X}/Makefile (100%) rename src/arch/pic32/{tneokernel.X => tneokernel_pic32.X}/nbproject/configurations.xml (100%) rename src/arch/pic32/{tneokernel.X => tneokernel_pic32.X}/nbproject/project.properties (100%) rename src/arch/pic32/{tneokernel.X => tneokernel_pic32.X}/nbproject/project.xml (93%) diff --git a/src/arch/pic32/tneokernel.X/Makefile b/src/arch/pic32/tneokernel_pic32.X/Makefile similarity index 100% rename from src/arch/pic32/tneokernel.X/Makefile rename to src/arch/pic32/tneokernel_pic32.X/Makefile diff --git a/src/arch/pic32/tneokernel.X/nbproject/configurations.xml b/src/arch/pic32/tneokernel_pic32.X/nbproject/configurations.xml similarity index 100% rename from src/arch/pic32/tneokernel.X/nbproject/configurations.xml rename to src/arch/pic32/tneokernel_pic32.X/nbproject/configurations.xml diff --git a/src/arch/pic32/tneokernel.X/nbproject/project.properties b/src/arch/pic32/tneokernel_pic32.X/nbproject/project.properties similarity index 100% rename from src/arch/pic32/tneokernel.X/nbproject/project.properties rename to src/arch/pic32/tneokernel_pic32.X/nbproject/project.properties diff --git a/src/arch/pic32/tneokernel.X/nbproject/project.xml b/src/arch/pic32/tneokernel_pic32.X/nbproject/project.xml similarity index 93% rename from src/arch/pic32/tneokernel.X/nbproject/project.xml rename to src/arch/pic32/tneokernel_pic32.X/nbproject/project.xml index d94b48b..51b6037 100644 --- a/src/arch/pic32/tneokernel.X/nbproject/project.xml +++ b/src/arch/pic32/tneokernel_pic32.X/nbproject/project.xml @@ -2,7 +2,7 @@ com.microchip.mplab.nbide.embedded.makeproject - tneokernel + tneokernel_pic32 455b33f3-b0bc-43d7-a5c4-84b529221aec 0 c From 194e16c98924b8cd009da4e3ee4bce77dbf060cb Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 19:26:26 +0300 Subject: [PATCH 79/96] pic32: updated examples and docs accordingly to new MPLABX project name --- .../nbproject/configurations.xml | 14 +++++++------- .../tn_pic32_example_basic.X/nbproject/project.xml | 2 +- .../nbproject/configurations.xml | 14 +++++++------- .../example_queue_pic32.X/nbproject/project.xml | 2 +- .../nbproject/configurations.xml | 14 +++++++------- .../nbproject/project.xml | 2 +- src/.vimprj/my.vim | 4 ++-- stuff/doc_pages/building.dox | 10 +++++----- stuff/doxygen/create_version_archive.sh | 4 ++-- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml b/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml index 0da1c7f..e61d6ef 100644 --- a/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml +++ b/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/configurations.xml @@ -43,20 +43,20 @@ - + OP="dist/default/production/tneokernel_pic32.X.a" + DOP="dist/default/debug/tneokernel_pic32.X.a" + FL="dist/default/production/tneokernel_pic32.X.a" + PD="dist/default/production/tneokernel_pic32.X." + DD="dist/default/debug/tneokernel_pic32.X."> diff --git a/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/project.xml b/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/project.xml index a14bf5d..7cc96c9 100644 --- a/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/project.xml +++ b/examples/basic/arch/pic32/tn_pic32_example_basic.X/nbproject/project.xml @@ -11,7 +11,7 @@ UTF-8 - ../../../../../src/arch/pic32/tneokernel.X + ../../../../../src/arch/pic32/tneokernel_pic32.X diff --git a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml index c1f0a00..23647c6 100644 --- a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml +++ b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml @@ -49,20 +49,20 @@ - + OP="dist/default/production/tneokernel_pic32.X.a" + DOP="dist/default/debug/tneokernel_pic32.X.a" + FL="dist/default/production/tneokernel_pic32.X.a" + PD="dist/default/production/tneokernel_pic32.X." + DD="dist/default/debug/tneokernel_pic32.X."> diff --git a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/project.xml b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/project.xml index f6b4300..58726e3 100644 --- a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/project.xml +++ b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/project.xml @@ -11,7 +11,7 @@ UTF-8 - ../../../../../src/arch/pic32/tneokernel.X + ../../../../../src/arch/pic32/tneokernel_pic32.X diff --git a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml index 211ccbd..4081037 100644 --- a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml +++ b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml @@ -49,20 +49,20 @@ - + OP="dist/default/production/tneokernel_pic32.X.a" + DOP="dist/default/debug/tneokernel_pic32.X.a" + FL="dist/default/production/tneokernel_pic32.X.a" + PD="dist/default/production/tneokernel_pic32.X." + DD="dist/default/debug/tneokernel_pic32.X."> diff --git a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/project.xml b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/project.xml index c09924e..158b6c8 100644 --- a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/project.xml +++ b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/project.xml @@ -11,7 +11,7 @@ UTF-8 - ../../../../../src/arch/pic32/tneokernel.X + ../../../../../src/arch/pic32/tneokernel_pic32.X diff --git a/src/.vimprj/my.vim b/src/.vimprj/my.vim index e82995b..8726f2b 100644 --- a/src/.vimprj/my.vim +++ b/src/.vimprj/my.vim @@ -16,7 +16,7 @@ let g:indexer_handlePath = 0 let g:indexer_ctagsCommandLineOptions = '--c++-kinds=+p+l --c-kinds=+l --fields=+iaS --extra=+q' -let s:o_dir = $INDEXER_PROJECT_ROOT.'/arch/pic32/tneokernel.X/build/tmp/compiled_in_vim' +let s:o_dir = $INDEXER_PROJECT_ROOT.'/arch/pic32/tneokernel_pic32.X/build/tmp/compiled_in_vim' if !isdirectory(s:o_dir) call mkdir(s:o_dir, "p") @@ -37,7 +37,7 @@ call CheckNeededSymbols( \ ] \ ) -let s:sProject = 'arch/pic32/tneokernel.X' +let s:sProject = 'arch/pic32/tneokernel_pic32.X' call envcontrol#set_project_file($INDEXER_PROJECT_ROOT.'/'.s:sProject, 'MPLAB_X', { \ 'parser_params': { diff --git a/stuff/doc_pages/building.dox b/stuff/doc_pages/building.dox index 2d8e08c..bfcbc68 100644 --- a/stuff/doc_pages/building.dox +++ b/stuff/doc_pages/building.dox @@ -32,11 +32,11 @@ and configure behavior as you like. \section building_pic32 PIC32 port: MPLABX project -MPLABX project resides in the `src/arch/pic32/tneokernel.X` directory. This is -a *library project* in terms of MPLABX, so if you use MPLABX you can easily add -it to your main project by right-clicking `Libraries -> Add Library Project -...`. Alternatively, of course you can just build it and use resulting -`tneokernel.X.a` file in whatever way you like. +MPLABX project resides in the `src/arch/pic32/tneokernel_pic32.X` directory. +This is a *library project* in terms of MPLABX, so if you use MPLABX you can +easily add it to your main project by right-clicking `Libraries -> Add Library +Project ...`. Alternatively, of course you can just build it and use +resulting `tneokernel_pic32.X.a` file in whatever way you like. \section building_pic24_dspic PIC24/dsPIC port: MPLABX project diff --git a/stuff/doxygen/create_version_archive.sh b/stuff/doxygen/create_version_archive.sh index 3a60539..335c688 100644 --- a/stuff/doxygen/create_version_archive.sh +++ b/stuff/doxygen/create_version_archive.sh @@ -31,14 +31,14 @@ hg clone $repo_path $tmp_repo_path pic32_bin="$tmp_repo_path/bin/pic32" -pushd src/arch/pic32/tneokernel.X +pushd src/arch/pic32/tneokernel_pic32.X make # in the target temp dir, create "bin" dir mkdir -p "$pic32_bin" # copy hex there -cp dist/default/production/tneokernel.X.a "$pic32_bin" +cp dist/default/production/tneokernel_pic32.X.a "$pic32_bin" # cd back popd From 01099fe08f602cef7c59bda04edc6c61549d1b38 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 19:35:05 +0300 Subject: [PATCH 80/96] tn_soft_isr() -> tn_p32_soft_isr(), tn_srs_isr() -> tn_p32_srs_isr() --- .../basic/arch/pic32/tn_pic32_example_basic.c | 2 +- examples/common/arch/pic32/pic32_arch.c | 2 +- src/arch/pic24_dspic/tn_arch_pic24.S | 2 +- src/arch/pic32/tn_arch_pic32.h | 22 ++++++++++++++----- stuff/doc_pages/changelog.dox | 2 +- stuff/doc_pages/pic32_details.dox | 4 ++-- stuff/doc_pages/quick_guide.dox | 2 +- 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/examples/basic/arch/pic32/tn_pic32_example_basic.c b/examples/basic/arch/pic32/tn_pic32_example_basic.c index 464f465..cf37cb6 100644 --- a/examples/basic/arch/pic32/tn_pic32_example_basic.c +++ b/examples/basic/arch/pic32/tn_pic32_example_basic.c @@ -118,7 +118,7 @@ struct TN_Task task_c = {}; /** * system timer ISR */ -tn_soft_isr(_TIMER_5_VECTOR) +tn_p32_soft_isr(_TIMER_5_VECTOR) { INTClearFlag(INT_T5); tn_tick_int_processing(); diff --git a/examples/common/arch/pic32/pic32_arch.c b/examples/common/arch/pic32/pic32_arch.c index ec6df96..c136f73 100644 --- a/examples/common/arch/pic32/pic32_arch.c +++ b/examples/common/arch/pic32/pic32_arch.c @@ -103,7 +103,7 @@ TN_STACK_ARR_DEF(interrupt_stack, INTERRUPT_STACK_SIZE); /** * system timer ISR */ -tn_soft_isr(_TIMER_5_VECTOR) +tn_p32_soft_isr(_TIMER_5_VECTOR) { INTClearFlag(INT_T5); tn_tick_int_processing(); diff --git a/src/arch/pic24_dspic/tn_arch_pic24.S b/src/arch/pic24_dspic/tn_arch_pic24.S index fbdb737..bb9edd6 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.S +++ b/src/arch/pic24_dspic/tn_arch_pic24.S @@ -284,7 +284,7 @@ __tn_arch_inside_isr: ; but it is actually should be false. ; ; Instead, on PIC24/dsPIC, system interrupts **must** use kernel-provided - ; macro tn_soft_isr() for interrupt definition, and we modify SPLIM there. + ; macro tn_p32_soft_isr() for interrupt definition, and we modify SPLIM there. ; So, here we check SPLIM, and if it points to _tn_p24_int_splim, ; we are inside interrupt. diff --git a/src/arch/pic32/tn_arch_pic32.h b/src/arch/pic32/tn_arch_pic32.h index 0163c83..3a55b0d 100644 --- a/src/arch/pic32/tn_arch_pic32.h +++ b/src/arch/pic32/tn_arch_pic32.h @@ -65,7 +65,7 @@ extern "C" { /*}*/ ******************************************************************************/ /// current interrupt nesting count. Used by macros -/// `tn_soft_isr()` and `tn_srs_isr()`. +/// `tn_p32_soft_isr()` and `tn_p32_srs_isr()`. extern volatile int tn_p32_int_nest_count; /// saved task stack pointer. Needed when switching stack pointer from @@ -312,7 +312,7 @@ typedef unsigned int TN_UIntPtr; * * Usage looks like the following: * - * tn_soft_isr(_TIMER_1_VECTOR) + * tn_p32_soft_isr(_TIMER_1_VECTOR) * { * INTClearFlag(INT_T1); * @@ -323,7 +323,7 @@ typedef unsigned int TN_UIntPtr; * * @param vec interrupt vector number, such as `_TIMER_1_VECTOR`, etc. */ -#define tn_soft_isr(vec) \ +#define tn_p32_soft_isr(vec) \ __attribute__((__noinline__)) void _func##vec(void); \ void __attribute__((naked, nomips16)) \ __attribute__((vector(vec))) \ @@ -461,7 +461,7 @@ void __attribute__((naked, nomips16)) \ * * Usage looks like the following: * - * tn_srs_isr(_INT_UART_1_VECTOR) + * tn_p32_srs_isr(_INT_UART_1_VECTOR) * { * INTClearFlag(INT_U1); * @@ -472,7 +472,7 @@ void __attribute__((naked, nomips16)) \ * * @param vec interrupt vector number, such as `_TIMER_1_VECTOR`, etc. */ -#define tn_srs_isr(vec) \ +#define tn_p32_srs_isr(vec) \ __attribute__((__noinline__)) void _func##vec(void); \ void __attribute__((naked, nomips16)) \ __attribute__((vector(vec))) \ @@ -567,6 +567,18 @@ void __attribute__((naked, nomips16)) \ } __attribute((__noinline__)) void _func##vec(void) +/** + * For compatibility with old projects, old name of `tn_p32_soft_isr()` macro + * is kept; please don't use it in new code. + */ +#define tn_soft_isr tn_p32_soft_isr + +/** + * For compatibility with old projects, old name of `tn_p32_srs_isr()` macro + * is kept; please don't use it in new code. + */ +#define tn_srs_isr tn_p32_srs_isr + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/stuff/doc_pages/changelog.dox b/stuff/doc_pages/changelog.dox index 639f5c2..2dd6b1d 100644 --- a/stuff/doc_pages/changelog.dox +++ b/stuff/doc_pages/changelog.dox @@ -29,7 +29,7 @@ Release date: 2014-10-20. project that demonstrates that technique is also available: `examples/queue_eventgrp_conn`. - PIC32 Interrupts: this isn't a mandatory anymore to use kernel-provided macros - `tn_soft_isr()` or `tn_srs_isr()`: interrupts can be defined with standard + `tn_p32_soft_isr()` or `tn_p32_srs_isr()`: interrupts can be defined with standard way too: this particular ISR will use task's stack instead of interrupt stack, therefore it takes much more RAM and works a bit faster. There are no additional constraints on ISR defined without kernel-provided macro: in diff --git a/stuff/doc_pages/pic32_details.dox b/stuff/doc_pages/pic32_details.dox index bf0d86a..1f38924 100644 --- a/stuff/doc_pages/pic32_details.dox +++ b/stuff/doc_pages/pic32_details.dox @@ -43,13 +43,13 @@ saving is supported. Usage is as follows: \code{.c} /* Timer 1 interrupt handler using software interrupt context saving */ -tn_soft_isr(_TIMER_1_VECTOR) +tn_p32_soft_isr(_TIMER_1_VECTOR) { /* here is your ISR code, including clearing of interrupt flag, and so on */ } /* High-priority UART interrupt handler using shadow register set */ -tn_srs_isr(_UART_1_VECTOR) +tn_p32_srs_isr(_UART_1_VECTOR) { /* here is your ISR code, including clearing of interrupt flag, and so on */ } diff --git a/stuff/doc_pages/quick_guide.dox b/stuff/doc_pages/quick_guide.dox index 2e5a804..95f09bd 100644 --- a/stuff/doc_pages/quick_guide.dox +++ b/stuff/doc_pages/quick_guide.dox @@ -17,7 +17,7 @@ function: \code{.c} //-- example for PIC32, hardware timer 5 interrupt: -tn_soft_isr(_TIMER_5_VECTOR) +tn_p32_soft_isr(_TIMER_5_VECTOR) { INTClearFlag(INT_T5); tn_tick_int_processing(); From c071646d1a5af16aa86bbc1d5fb62a904b300e4c Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 19:42:03 +0300 Subject: [PATCH 81/96] updated changelog: added information about refactoring --- stuff/doc_pages/changelog.dox | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/stuff/doc_pages/changelog.dox b/stuff/doc_pages/changelog.dox index 2dd6b1d..b5e9487 100644 --- a/stuff/doc_pages/changelog.dox +++ b/stuff/doc_pages/changelog.dox @@ -16,6 +16,15 @@ TNeoKernel changelog because non-prefixed symbols may be defined by some other program module, which leads to conflicts. The easiest and robust way is to add unique prefix. + - Refactor: PIC32 MPLABX project renamed from `tneokernel.X` to + `tneokernel_pic32.X`. + - Refactor: PIC32 ISR macros renamed: `tn_soft_isr()` -> + `tn_p32_soft_isr()`, `tn_srs_isr()` -> `tn_p32_srs_isr()`. It is much + easier to maintain documentation for different macros if they have + different names; more, the signature of these macros is + architecture-dependent. Old names are also available for backward + compatibility. + \section changelog_v1_03 v1.03 From b418b0b5bfc3543af05f549a2a6cb4be76deff1a Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Mon, 3 Nov 2014 23:23:59 +0300 Subject: [PATCH 82/96] pic24 basic example: removed csp stuff, used standard #pragma config expressions --- .../basic/arch/pic24/tn_pic24_example_basic.c | 210 ++---------------- 1 file changed, 19 insertions(+), 191 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index fb58ff4..7600160 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -16,197 +16,25 @@ * HARDWARE CONFIGURATION ******************************************************************************/ -// {{{ - - -/* - - Config word 3 Example: Protect code memory from start (protect 128 flash pages) and protect - configuration block of programm memoty - - __CSP_CONFIG_3(CODE_WRITE_PROT_MEM_START | - CODE_WRITE_CONF_MEM_EN | - (128) - ); - */ - -#define __CSP_CONFIG_3(x) __attribute__((section("__CONFIG3.sec,code"))) int __CSP_CONFIG_3 = ((x) | 0x1E00) - -/* Write protection location */ - -#define CODE_WRITE_PROT_MEM_START (0 << 15) /* Code write protect from start of programm memory */ -#define CODE_WRITE_PROT_MEM_END (1 << 15) /* Code write protect from end of programm memory */ - -/* Write Protect Configuration Page */ - -#define CODE_WRITE_CONF_MEM_EN (1 << 14) /* Code configuration memory block write protect enabled */ -#define CODE_WRITE_CONF_MEM_DIS (0 << 14) /* Code configuration memory block write protect disabled */ - -/* Write protect enable */ - -#define CODE_WRITE_BLOCK_EN (0 << 13) /* Code write protect enabled */ -#define CODE_WRITE_BLOCK_DIS (1 << 13) /* Code write protect disabled */ - - -#define __CSP_CONFIG_2(x) __attribute__((section("__CONFIG2.sec,code"))) int __CSP_CONFIG_2 = ((x) | 0x0004) - -/* Two Speed Start-up: */ - -#define TWO_SPEED_STARTUP_EN (1 << 15) /* Enabled */ -#define TWO_SPEED_STARTUP_DIS (0 << 15) /* Disabled */ - -/* USB 96 MHz PLL Prescaler Select bits */ - -#define USB_PLL_PRESCALE_1 (0 << 12) /* 1:1 */ -#define USB_PLL_PRESCALE_2 (1 << 12) /* 1:2 */ -#define USB_PLL_PRESCALE_3 (2 << 12) /* 1:3 */ -#define USB_PLL_PRESCALE_4 (3 << 12) /* 1:4 */ -#define USB_PLL_PRESCALE_5 (4 << 12) /* 1:5 */ -#define USB_PLL_PRESCALE_6 (5 << 12) /* 1:6 */ -#define USB_PLL_PRESCALE_10 (6 << 12) /* 1:10 */ -#define USB_PLL_PRESCALE_12 (7 << 12) /* 1:12 */ - -/* Oscillator Selection: */ - -#define OSC_STARTUP_FRC (0 << 8) /* Fast RC oscillator */ -#define OSC_STARTUP_FRC_PLL (1 << 8) /* Fast RC oscillator w/ divide and PLL */ -#define OSC_STARTUP_PRIMARY (2 << 8) /* Primary oscillator (XT, HS, EC) */ -#define OSC_STARTUP_PRIMARY_PLL (3 << 8) /* Primary oscillator (XT, HS, EC) w/ PLL */ -#define OSC_STARTUP_SECONDARY (4 << 8) /* Secondary oscillator */ -#define OSC_STARTUP_LPRC (5 << 8) /* Low power RC oscillator */ -#define OSC_STARTUP_FRC_PS (7 << 8) /* Fast RC oscillator with divide */ - -/* Clock switching and clock montor: */ - -#define CLK_SW_EN_CLK_MON_EN (0 << 6) /* Both enabled */ -#define CLK_SW_EN_CLK_MON_DIS (1 << 6) /* Only clock switching enabled */ -#define CLK_SW_DIS_CLK_MON_DIS (3 << 6) /* Both disabled */ - -/* OSCO/RC15 function: */ - -#define OSCO_PIN_CLKO (1 << 5) /* OSCO or Fosc/2 */ -#define OSCO_PIN_GPIO (0 << 5) /* RC15 */ - -/* RP Register Protection */ - -#define PPS_REG_PROTECT_DIS (0 << 4) /* Unlimited Writes To RP Registers */ -#define PPS_REG_PROTECT_EN (1 << 4) /* Write RP Registers Once */ - -/* USB regulator control */ - -#define USB_REG_EN (0 << 3) -#define USB_REG_DIS (1 << 3) - -/* Oscillator Selection: */ - -#define PRIMARY_OSC_EC (0 << 0) /* External clock */ -#define PRIMARY_OSC_XT (1 << 0) /* XT oscillator */ -#define PRIMARY_OSC_HS (2 << 0) /* HS oscillator */ -#define PRIMARY_OSC_DIS (3 << 0) /* Primary disabled */ - - - -#define __CSP_CONFIG_1(x) __attribute__((section("__CONFIG1.sec,code"))) int __CSP_CONFIG_1 = ((x) | 0x8420) - -/* JTAG: */ - -#define JTAG_EN (1 << 14) /* Enabled */ -#define JTAG_DIS (0 << 14) /* Disabled */ - -/* Code Protect: */ - -#define CODE_PROTECT_EN (0 << 13) /* Enabled */ -#define CODE_PROTECT_DIS (1 << 13) /* Disabled */ - -/* Write Protect: */ - -#define CODE_WRITE_EN (1 << 12) /* Enabled */ -#define CODE_WRITE_DIS (0 << 12) /* Disabled */ - -/* Background Debugger: */ - -#define BACKGROUND_DEBUG_EN (0 << 11) /* Enabled */ -#define BACKGROUND_DEBUG_DIS (1 << 11) /* Disabled */ - -/* Clip-on Emulation mode: */ - -#define EMULATION_EN (0 << 10) /* Enabled */ -#define EMULATION_DIS (1 << 10) /* Disabled */ - -/* ICD pins select: */ - -#define ICD_PIN_PGX3 (1 << 8) /* EMUC/EMUD share PGC3/PGD3 */ -#define ICD_PIN_PGX2 (2 << 8) /* EMUC/EMUD share PGC2/PGD2 */ -#define ICD_PIN_PGX1 (3 << 8) /* EMUC/EMUD share PGC1/PGD1 */ - -/* Watchdog Timer: */ - -#define WDT_EN (1 << 7) /* Enabled */ -#define WDT_DIS (0 << 7) /* Disabled */ - -/* Windowed WDT: */ - -#define WDT_WINDOW_EN (0 << 6) /* Enabled */ -#define WDT_WINDOW_DIS (1 << 6) /* Disabled */ - -/* Watchdog prescaler: */ - -#define WDT_PRESCALE_32 (0 << 4) /* 1:32 */ -#define WDT_PRESCALE_128 (1 << 4) /* 1:128 */ - - -/* Watchdog postscale: */ - -#define WDT_POSTSCALE_1 ( 0 << 0) /* 1:1 */ -#define WDT_POSTSCALE_2 ( 1 << 0) /* 1:2 */ -#define WDT_POSTSCALE_4 ( 2 << 0) /* 1:4 */ -#define WDT_POSTSCALE_8 ( 3 << 0) /* 1:8 */ -#define WDT_POSTSCALE_16 ( 4 << 0) /* 1:16 */ -#define WDT_POSTSCALE_32 ( 5 << 0) /* 1:32 */ -#define WDT_POSTSCALE_64 ( 6 << 0) /* 1:64 */ -#define WDT_POSTSCALE_128 ( 7 << 0) /* 1:128 */ -#define WDT_POSTSCALE_256 ( 8 << 0) /* 1:256 */ -#define WDT_POSTSCALE_512 ( 9 << 0) /* 1:512 */ -#define WDT_POSTSCALE_1024 (10 << 0) /* 1:1024 */ -#define WDT_POSTSCALE_2048 (11 << 0) /* 1:2048 */ -#define WDT_POSTSCALE_4096 (12 << 0) /* 1:4096 */ -#define WDT_POSTSCALE_8192 (13 << 0) /* 1:8192 */ -#define WDT_POSTSCALE_16384 (14 << 0) /* 1:16384 */ -#define WDT_POSTSCALE_32768 (15 << 0) /* 1:32768 */ - -// }}} - - -__CSP_CONFIG_1( - JTAG_DIS | /* JTAG disabled */ - CODE_PROTECT_DIS | /* Code Protect disabled */ - CODE_WRITE_EN | /* Code write enabled */ - BACKGROUND_DEBUG_EN | /* Debug enabled */ - EMULATION_EN | /* Emulation enabled */ - ICD_PIN_PGX2 | /* PGC2/PGD2 pins used for debug */ - WDT_DIS | /* WDT disabled */ - WDT_WINDOW_DIS | /* WDT mode is not-windowed */ - WDT_PRESCALE_32 | /* WDT prescale is 1:32 */ - WDT_POSTSCALE_1 /* WDT postscale is 1:1 */ - ); - -__CSP_CONFIG_2( - TWO_SPEED_STARTUP_DIS | /* Two-speed startup disabled */ - USB_PLL_PRESCALE_4 | - OSC_STARTUP_PRIMARY_PLL | /* Startup oscillator is Primary with PLL */ - CLK_SW_DIS_CLK_MON_DIS | /* Clock switch disabled, monitor disabled */ - OSCO_PIN_CLKO | /* OSCO pin is clockout */ - PPS_REG_PROTECT_DIS | /* PPS runtime change enabled */ - USB_REG_DIS | - PRIMARY_OSC_HS /* Primary oscillator mode is HS */ - ); - -__CSP_CONFIG_3( - CODE_WRITE_PROT_MEM_START | /* Code write protect block from start */ - CODE_WRITE_CONF_MEM_DIS | /* Code config memory block not protected */ - CODE_WRITE_BLOCK_DIS /* Code block protect disabled */ - ); - +#pragma config JTAGEN = OFF //-- JTAG disabled +#pragma config GCP = OFF //-- Code protect off +#pragma config GWRP = OFF //-- Code write enabled +#pragma config BKBUG = ON //-- Debug enabled +#pragma config FWDTEN = OFF //-- Watchdog disabled + +#pragma config WPDIS = WPDIS //-- Segmented code protection disabled +#pragma config WPCFG = WPCFGDIS //-- Last page and config words protection + // disabled +#pragma config POSCMOD = HS //-- HS oscillator +#pragma config FNOSC = PRIPLL //-- Primary oscillator (XT, HS, EC) with + // PLL module +#pragma config IESO = OFF //-- Two-speed start-up disabled +#pragma config OSCIOFNC = ON //-- OSCO functions as OSCO (FOSC / 2), + // not as GPIO +#pragma config PLLDIV = DIV4 //-- Osc input divided by 4 (16 MHz) +#pragma config COE = ON //-- Clip on emulation mode enabled +#pragma config ICS = PGx2 //-- Emulator functions are shared with + // PGEC2/PGED2 From 0c6d13079c626426787164ccdb811c8d551d270a Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 00:35:52 +0300 Subject: [PATCH 83/96] pic24: TN_BFA() macro is now public, it is used in the basic example --- .../basic/arch/pic24/tn_pic24_example_basic.c | 52 ++-- src/arch/pic24_dspic/tn_arch_pic24.h | 3 + src/arch/pic24_dspic/tn_arch_pic24_bfa.h | 286 +++++++++++------- src/arch/pic24_dspic/tn_arch_pic24_c.c | 8 +- stuff/doc_pages/pic24_details.dox | 21 ++ stuff/doxygen/tn_doxyfile | 3 +- 6 files changed, 234 insertions(+), 139 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index 7600160..47b3506 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -118,7 +118,10 @@ struct TN_Task task_c = {}; tn_p24_soft_isr(_T1Interrupt, auto_psv) { - IFS0bits.T1IF = 0; + //-- clear interrupt flag + TN_BFA(TN_BFA_WR, IFS0, T1IF, 0); + + //-- proceed system tick tn_tick_int_processing(); } @@ -140,7 +143,8 @@ void task_a_body(void *par) // (job for which task was created at all) for(;;) { - __builtin_btg(&LATE, 0); + //-- atomically invert LATEbits.LATE0 + TN_BFA(TN_BFA_INV, LATE, LATE0, 1); tn_task_sleep(500); } } @@ -149,7 +153,8 @@ void task_b_body(void *par) { for(;;) { - __builtin_btg(&LATE, 1); + //-- atomically invert LATEbits.LATE1 + TN_BFA(TN_BFA_INV, LATE, LATE1, 1); tn_task_sleep(1000); } } @@ -158,7 +163,8 @@ void task_c_body(void *par) { for(;;) { - __builtin_btg(&LATE, 2); + //-- atomically invert LATEbits.LATE2 + TN_BFA(TN_BFA_INV, LATE, LATE2, 1); tn_task_sleep(1500); } } @@ -169,17 +175,22 @@ void task_c_body(void *par) void hw_init(void) { //-- set up timer1 - T1CONbits.TCS = 0; - T1CONbits.TGATE = 0; - T1CONbits.TSIDL = 1; - - T1CONbits.TCKPS = 2; // 1:64 - PR1 = (SYS_TMR_PERIOD - 1); - - IFS0bits.T1IF = 0; - IEC0bits.T1IE = 1; - IPC0bits.T1IP = 2; - T1CONbits.TON = 1; + TN_BFA(TN_BFA_WR, T1CON, TCS, 0); + TN_BFA(TN_BFA_WR, T1CON, TGATE, 0); + TN_BFA(TN_BFA_WR, T1CON, TSIDL, 1); + + //-- set prescaler: 1:64 + TN_BFA(TN_BFA_WR, T1CON, TCKPS, 2); + //-- set period + PR1 = (SYS_TMR_PERIOD - 1); + + //-- set timer1 interrupt + TN_BFA(TN_BFA_WR, IPC0, T1IP, 2); //-- set timer1 interrupt priority: 2 + TN_BFA(TN_BFA_WR, IFS0, T1IF, 0); //-- clear interrupt flag + TN_BFA(TN_BFA_WR, IEC0, T1IE, 1); //-- enable interrupt + + //-- eventually, turn the timer on + TN_BFA(TN_BFA_WR, T1CON, TON, 1); } /** @@ -187,11 +198,11 @@ void hw_init(void) */ void appl_init(void) { - //-- configure LED port pins + //-- configure LED port pins to output - TRISEbits.TRISE0 = 0; - TRISEbits.TRISE1 = 0; - TRISEbits.TRISE2 = 0; + TN_BFA(TN_BFA_WR, TRISE, TRISE0, 0); + TN_BFA(TN_BFA_WR, TRISE, TRISE1, 0); + TN_BFA(TN_BFA_WR, TRISE, TRISE2, 0); //-- initialize various on-board peripherals, such as // flash memory, displays, etc. @@ -270,6 +281,9 @@ int main(void) +/******************************************************************************* + * ERROR TRAPS + ******************************************************************************/ void __attribute((__interrupt__, auto_psv)) _AddressError (void) { diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index 9fb0af0..f6b1e93 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -47,6 +47,9 @@ #include "../../core/tn_cfg_dispatch.h" +//-- include macros for atomic assess to structure bit fields so that +// application can use it too. +#include "tn_arch_pic24_bfa.h" #ifdef __cplusplus extern "C" { /*}*/ diff --git a/src/arch/pic24_dspic/tn_arch_pic24_bfa.h b/src/arch/pic24_dspic/tn_arch_pic24_bfa.h index a74ddeb..bbc0132 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_bfa.h +++ b/src/arch/pic24_dspic/tn_arch_pic24_bfa.h @@ -37,11 +37,15 @@ /** * \file * - * Atomic bit-field access macros. + * Atomic bit-field access macros for PIC24/dsPIC. * - * Author: Alex Borisov, his article in russian could be found here: - * http://www.pic24.ru/doku.php/articles/mchp/c30_atomic_access + * Initially, the code was taken from the [article by Alex Borisov + * (russian)](http://www.pic24.ru/doku.php/articles/mchp/c30_atomic_access), + * and modified a bit. * + * The kernel would not probably provide that kind of functionality, but + * the kernel itself needs it, so, it is made public so that application can + * use it too. */ #ifndef _TN_ARCH_PIC24_BFA_H @@ -66,128 +70,182 @@ extern "C" { /*}*/ /* Access params */ -#define BFA_SET 0x1111 -#define BFA_CLR 0x2222 -#define BFA_INV 0x3333 /* invert bit field */ +/// +/// Command for `TN_BFA()` macro: Set bits in the bit field by mask; +/// `...` macro param should be set to the bit mask to set. +/// +/// Example: +/// \code{.c} +/// //-- Set third bit of the INT0IP field in the IPC0 register: +/// // IPC0bits.INT0IP |= (1 << 2); +/// TN_BFA(TN_BFA_SET, IPC0, INT0IP, (1 << 2)); +/// \endcode +#define TN_BFA_SET 0x1111 +/// +/// Command for `TN_BFA()` macro: Clear bits in the bit field by mask; +/// `...` macro param should be set to the bit mask to clear. +/// +/// Example: +/// \code{.c} +/// //-- Clear second bit of the INT0IP field in the IPC0 register: +/// // IPC0bits.INT0IP &= ~(1 << 1); +/// TN_BFA(TN_BFA_CLR, IPC0, INT0IP, (1 << 1)); +/// \endcode +#define TN_BFA_CLR 0x2222 +/// +/// Command for `TN_BFA()` macro: Invert bits in the bit field by mask; +/// `...` macro param should be set to the bit mask to invert. +/// +/// Example: +/// \code{.c} +/// //-- Invert two less-significant bits of the INT0IP field +/// // in the IPC0 register: +/// // IPC0bits.INT0IP ^= 0x03; +/// TN_BFA(TN_BFA_INV, IPC0, INT0IP, 0x03); +/// \endcode +#define TN_BFA_INV 0x3333 +/// +/// Command for `TN_BFA()` macro: Write bit field; +/// `...` macro param should be set to the value to write. +/// +/// Example: +/// \code{.c} +/// //-- Write value 0x05 to the INT0IP field of the IPC0 register: +/// // IPC0bits.INT0IP = 0x05; +/// TN_BFA(TN_BFA_WR, IPC0, INT0IP, 0x05); +/// +/// //-- Write value of the variable a to the INT0IP field of the IPC0 +/// // register: +/// // IPC0bits.INT0IP = a; +/// TN_BFA(TN_BFA_WR, IPC0, INT0IP, a); +/// \endcode +#define TN_BFA_WR 0xAAAA +/// +/// Command for `TN_BFA()` macro: Read bit field; +/// `...` macro param ignored. +/// +/// Example: +/// \code{.c} +/// //-- Read the value that is stored in the INT0IP field of the IPC0 +/// // register, to the int variable a: +/// // int a = IPC0bits.INT0IP; +/// int a = TN_BFA(TN_BFA_RD, IPC0, INT0IP); +/// \endcode +#define TN_BFA_RD 0xBBBB -#define BFA_WR 0xAAAA /* write bit field */ -#define BFA_RD 0xBBBB /* read bit field */ -#define __BFA_COMM_ERR(a) __BFA_COMMAND_ERROR_##a -#define __BFA_COMM_GET(a) __BFA_COMM_ERR(a) - -typedef unsigned int __BFA_COMM_GET(BFA_SET); -typedef unsigned int __BFA_COMM_GET(BFA_CLR); -typedef unsigned int __BFA_COMM_GET(BFA_INV); - -typedef unsigned int __BFA_COMM_GET(BFA_WR); -typedef unsigned int __BFA_COMM_GET(BFA_RD); - -#define __BFA_STRUCT_TYPE(a) a##BITS -#define __BFA_STRUCT_VAL(a) a##bits /** - * Macro for atomic access to structure field. + * Macro for atomic access to the structure bit field. The `BFA` acronym + * means Bit Field Access. + * + * @param comm + * command to execute: + * - `#TN_BFA_WR` - write bit field + * - `#TN_BFA_RD` - read bit field + * - `#TN_BFA_SET` - set bit fields by mask + * - `#TN_BFA_CLR` - clear bit fields by mask + * - `#TN_BFA_INV` - invert bit fields by mask + * + * @param reg_name + * register name (`PORTA`, `CMCON`, ...). + * + * @param field_name + * structure field name * - * comm - command to execute - * - BFA_WR - write bit field - * - BFA_RD - read bit field - * - BFA_SET - set bit fields by mask - * - BFA_CLR - clear bit fields by mask - * - BFA_INV - invert bit fields by mask - * reg_name - register name (PORTA, CMCON, ...). - * field_name - structure field name - * ... - used if only comm = BFA_WR. Should be equal to the value - * to write to field. You can use variable here. + * @param ... + * used if only `comm != #TN_BFA_RD`. Should be equal to the value to + * write to field. You can use variable here. * - * Usage examples: - * BFA(BFA_WR, IPC0, INT0IP, 0); - * BFA(BFA_INV, IPC0, INT0IP, 1); - * a = BFA(BFA_RD, IPC0, INT0IP); - * BFA(BFA_WR, IPC0, INT0IP, a); - * BFA(BFA_SET, IPC0, INT0IP, (1 << 2)); + * See usage examples for each of the commands: `#TN_BFA_WR`, etc. */ -#define BFA(comm, reg_name, field_name, ...) \ - ({ \ - union \ - { \ - __BFA_STRUCT_TYPE(reg_name) o; \ - unsigned int i; \ - } lcur, lmask={}, lval={}; \ - \ - lmask.o.field_name = -1; \ - \ - ((comm) == BFA_WR) \ - ?({ \ - __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ - if (lmask.i & (lmask.i-1)) \ - { \ - lval.o.field_name = v; \ - lcur.o = __BFA_STRUCT_VAL(reg_name); \ - __asm__ __volatile__ \ - ("xor %0":"=U"(reg_name):"a"(lmask.i & (lval.i^lcur.i))); \ - } \ - else \ - { \ - if (v & 1) \ - { \ - __BFA_STRUCT_VAL(reg_name).field_name = 1; \ - } \ - else \ - { \ - __BFA_STRUCT_VAL(reg_name).field_name = 0; \ - } \ - } \ - }), 0 \ - \ - :(((comm) == BFA_INV) \ - ?({ \ - __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ - lval.o.field_name = v; \ - __asm__ __volatile__(" xor %0" \ - :"=U"(reg_name):"a"(lmask.i & lval.i)); \ - }), 0 \ - \ - :((((comm) == BFA_SET) \ - ?({ \ - __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ - if (lmask.i & (lmask.i-1)) \ - { \ - lval.o.field_name = v; \ - __asm__ __volatile__ \ - ("ior %0":"=U"(reg_name):"a"(lmask.i & lval.i)); \ - } \ - else \ - { \ - if (v & 1) \ - __BFA_STRUCT_VAL(reg_name).field_name = 1; \ - } \ - }), 0 \ - \ - :(((((comm) == BFA_CLR) \ - ?({ \ - __BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ - if (lmask.i & (lmask.i-1)) \ - { \ - lval.o.field_name = v; \ - __asm__ __volatile__ \ - ("and %0":"=U"(reg_name):"a"(~(lmask.i & lval.i))); \ - } \ - else \ - { \ - if (v & 1) \ - __BFA_STRUCT_VAL(reg_name).field_name = 0; \ - } \ - }), 0 \ - \ - :({ /* BFA_RD */ \ - __BFA_STRUCT_VAL(reg_name).field_name; \ - }))))))); \ - }) +#define TN_BFA(comm, reg_name, field_name, ...) \ + ({ \ + union \ + { \ + _TN_BFA_STRUCT_TYPE(reg_name) o; \ + unsigned int i; \ + } lcur, lmask={}, lval={}; \ + \ + lmask.o.field_name = -1; \ + \ + ((comm) == TN_BFA_WR) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask.i & (lmask.i-1)){ \ + lval.o.field_name = v; \ + lcur.o = _TN_BFA_STRUCT_VAL(reg_name); \ + __asm__ __volatile__ \ + ("xor %0":"=U"(reg_name):"a"(lmask.i & (lval.i^lcur.i))); \ + } else { \ + if (v & 1) \ + { \ + _TN_BFA_STRUCT_VAL(reg_name).field_name = 1; \ + } else { \ + _TN_BFA_STRUCT_VAL(reg_name).field_name = 0; \ + } \ + } \ + }), 0 \ + \ + :(((comm) == TN_BFA_INV) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + lval.o.field_name = v; \ + __asm__ __volatile__(" xor %0" \ + :"=U"(reg_name):"a"(lmask.i & lval.i)); \ + }), 0 \ + \ + :((((comm) == TN_BFA_SET) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask.i & (lmask.i-1)){ \ + lval.o.field_name = v; \ + __asm__ __volatile__ \ + ("ior %0":"=U"(reg_name):"a"(lmask.i & lval.i)); \ + } else { \ + if (v & 1) \ + _TN_BFA_STRUCT_VAL(reg_name).field_name = 1; \ + } \ + }), 0 \ + \ + :(((((comm) == TN_BFA_CLR) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask.i & (lmask.i-1)){ \ + lval.o.field_name = v; \ + __asm__ __volatile__ \ + ("and %0":"=U"(reg_name):"a"(~(lmask.i & lval.i))); \ + } else { \ + if (v & 1) \ + _TN_BFA_STRUCT_VAL(reg_name).field_name = 0; \ + } \ + }), 0 \ + \ + :({ /* TN_BFA_RD */ \ + _TN_BFA_STRUCT_VAL(reg_name).field_name; \ + }))))))); \ + }) +//-- internal kernel macros {{{ +#ifndef DOXYGEN_SHOULD_SKIP_THIS +#define _TN_BFA_COMM_ERR(a) _TN_BFA_COMMAND_ERROR_##a +#define _TN_BFA_COMM_GET(a) _TN_BFA_COMM_ERR(a) + +typedef unsigned int _TN_BFA_COMM_GET(TN_BFA_SET); +typedef unsigned int _TN_BFA_COMM_GET(TN_BFA_CLR); +typedef unsigned int _TN_BFA_COMM_GET(TN_BFA_INV); + +typedef unsigned int _TN_BFA_COMM_GET(TN_BFA_WR); +typedef unsigned int _TN_BFA_COMM_GET(TN_BFA_RD); + +#define _TN_BFA_STRUCT_TYPE(a) a##BITS +#define _TN_BFA_STRUCT_VAL(a) a##bits + +#endif +// }}} #ifdef __cplusplus diff --git a/src/arch/pic24_dspic/tn_arch_pic24_c.c b/src/arch/pic24_dspic/tn_arch_pic24_c.c index da8819a..489d2c6 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_c.c +++ b/src/arch/pic24_dspic/tn_arch_pic24_c.c @@ -71,10 +71,10 @@ void _tn_arch_sys_init( //-- set up software interrupt for context switching - BFA(BFA_WR, IPC0, INT0IP, 1); //-- set lowest interrupt priority - // for context switch interrupt - BFA(BFA_WR, IFS0, INT0IF, 0); //-- clear interrupt flag - BFA(BFA_WR, IEC0, INT0IE, 1); //-- enable interrupt + TN_BFA(TN_BFA_WR, IPC0, INT0IP, 1); //-- set lowest interrupt priority + // for context switch interrupt + TN_BFA(TN_BFA_WR, IFS0, INT0IF, 0); //-- clear interrupt flag + TN_BFA(TN_BFA_WR, IEC0, INT0IE, 1); //-- enable interrupt } diff --git a/stuff/doc_pages/pic24_details.dox b/stuff/doc_pages/pic24_details.dox index f3f9508..6f23e63 100644 --- a/stuff/doc_pages/pic24_details.dox +++ b/stuff/doc_pages/pic24_details.dox @@ -69,4 +69,25 @@ interrupt of priority higher than `#TN_P24_SYS_IPL`). Use standard way to define it. If you violate this rule, debugger will be halted by the kernel when entering ISR. In release build, CPU is just reset. + +\section pic24_bfa Atomic access to the structure bit field + +The problem with PIC24/dsPIC is that when we write something like: + +\code{.c} +IPC0bits.INT0IP = 0x05; +\endcode + +We actually have read-modify-write sequence which can be interrupted, so that +resulting data could be corrupted. PIC24/dsPIC port provides `TN_BFA()` macro +that provides atomic access to the structure bit field. + +The kernel would not probably provide that kind of functionality, but +TNeoKernel itself needs it, so, it is made public so that application can +use it too. + +Refer to the page \ref tn_arch_pic24_bfa.h "Atomic bit-field access macros" +for details. + + */ diff --git a/stuff/doxygen/tn_doxyfile b/stuff/doxygen/tn_doxyfile index ea1171d..a4e8c15 100644 --- a/stuff/doxygen/tn_doxyfile +++ b/stuff/doxygen/tn_doxyfile @@ -809,8 +809,7 @@ RECURSIVE = YES # run. EXCLUDE = ../../src/tn_cfg.h \ - ../../src/arch/tn_arch_detect.h \ - ../../src/arch/pic24_dspic/tn_arch_pic24_bfa.h + ../../src/arch/tn_arch_detect.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded From d7a0151443f32af4797874eda6d342f52218349a Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 01:07:41 +0300 Subject: [PATCH 84/96] queue_example is implemented for pic24 --- .../basic/arch/pic24/tn_pic24_example_basic.c | 8 +- examples/common/arch/pic24/example_arch.h | 41 ++ examples/common/arch/pic24/pic24_arch.c | 206 ++++++++++ .../arch/pic24/example_queue_pic24.X/Makefile | 113 +++++ .../nbproject/configurations.xml | 389 ++++++++++++++++++ .../nbproject/project.properties | 0 .../nbproject/project.xml | 18 + examples/queue/arch/pic24/pic24_arch.c | 4 + .../queue/arch/pic24/queue_example_arch.c | 63 +++ .../queue/arch/pic24/queue_example_arch.h | 15 + .../nbproject/configurations.xml | 7 +- .../queue/arch/pic32/queue_example_arch.h | 11 - examples/queue/queue_example.h | 16 + 13 files changed, 877 insertions(+), 14 deletions(-) create mode 100644 examples/common/arch/pic24/example_arch.h create mode 100644 examples/common/arch/pic24/pic24_arch.c create mode 100644 examples/queue/arch/pic24/example_queue_pic24.X/Makefile create mode 100644 examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml create mode 100644 examples/queue/arch/pic24/example_queue_pic24.X/nbproject/project.properties create mode 100644 examples/queue/arch/pic24/example_queue_pic24.X/nbproject/project.xml create mode 100644 examples/queue/arch/pic24/pic24_arch.c create mode 100644 examples/queue/arch/pic24/queue_example_arch.c create mode 100644 examples/queue/arch/pic24/queue_example_arch.h diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.c b/examples/basic/arch/pic24/tn_pic24_example_basic.c index 47b3506..7ae9f1c 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.c +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.c @@ -49,16 +49,20 @@ //-- system frequency #define SYS_FREQ 32000000UL +//-- peripheral bus frequency +#define PB_FREQ (SYS_FREQ / 2) + //-- kernel ticks (system timer) frequency #define SYS_TMR_FREQ 1000 //-- system timer prescaler //#define SYS_TMR_PRESCALER T5_PS_1_8 #define SYS_TMR_PRESCALER_VALUE 64 +#define SYS_TMR_PRESCALER_REGVALUE 2 //-- system timer period (auto-calculated) #define SYS_TMR_PERIOD \ - (SYS_FREQ / SYS_TMR_PRESCALER_VALUE / SYS_TMR_FREQ) + (PB_FREQ / SYS_TMR_PRESCALER_VALUE / SYS_TMR_FREQ) @@ -180,7 +184,7 @@ void hw_init(void) TN_BFA(TN_BFA_WR, T1CON, TSIDL, 1); //-- set prescaler: 1:64 - TN_BFA(TN_BFA_WR, T1CON, TCKPS, 2); + TN_BFA(TN_BFA_WR, T1CON, TCKPS, SYS_TMR_PRESCALER_REGVALUE); //-- set period PR1 = (SYS_TMR_PERIOD - 1); diff --git a/examples/common/arch/pic24/example_arch.h b/examples/common/arch/pic24/example_arch.h new file mode 100644 index 0000000..3b121a0 --- /dev/null +++ b/examples/common/arch/pic24/example_arch.h @@ -0,0 +1,41 @@ +/******************************************************************************* + * Description: TODO + * + ******************************************************************************/ + +#ifndef _EXAMPLE_ARCH_H +#define _EXAMPLE_ARCH_H + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +/******************************************************************************* + * PUBLIC TYPES + ******************************************************************************/ + +/******************************************************************************* + * GLOBAL VARIABLES + ******************************************************************************/ + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + +//-- instruction that causes debugger to halt +#define SOFTWARE_BREAK() {__asm__ volatile(".pword 0xDA4000"); __asm__ volatile ("nop");} + + +/******************************************************************************* + * PUBLIC FUNCTION PROTOTYPES + ******************************************************************************/ + + +#endif // _EXAMPLE_ARCH_H + + +/******************************************************************************* + * end of file + ******************************************************************************/ + + diff --git a/examples/common/arch/pic24/pic24_arch.c b/examples/common/arch/pic24/pic24_arch.c new file mode 100644 index 0000000..9408e12 --- /dev/null +++ b/examples/common/arch/pic24/pic24_arch.c @@ -0,0 +1,206 @@ +/** + * TNeoKernel PIC32 basic example + */ + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include +#include "tn.h" + +#include "example_arch.h" + + + +/******************************************************************************* + * PIC32 HARDWARE CONFIGURATION + ******************************************************************************/ + +#pragma config JTAGEN = OFF //-- JTAG disabled +#pragma config GCP = OFF //-- Code protect off +#pragma config GWRP = OFF //-- Code write enabled +#pragma config BKBUG = ON //-- Debug enabled +#pragma config FWDTEN = OFF //-- Watchdog disabled + +#pragma config WPDIS = WPDIS //-- Segmented code protection disabled +#pragma config WPCFG = WPCFGDIS //-- Last page and config words protection + // disabled +#pragma config POSCMOD = HS //-- HS oscillator +#pragma config FNOSC = PRIPLL //-- Primary oscillator (XT, HS, EC) with + // PLL module +#pragma config IESO = OFF //-- Two-speed start-up disabled +#pragma config OSCIOFNC = ON //-- OSCO functions as OSCO (FOSC / 2), + // not as GPIO +#pragma config PLLDIV = DIV4 //-- Osc input divided by 4 (16 MHz) +#pragma config COE = ON //-- Clip on emulation mode enabled +#pragma config ICS = PGx2 //-- Emulator functions are shared with + // PGEC2/PGED2 + + + +/******************************************************************************* + * MACROS + ******************************************************************************/ + +//-- system frequency +#define SYS_FREQ 32000000UL + +//-- peripheral bus frequency +#define PB_FREQ (SYS_FREQ / 2) + +//-- kernel ticks (system timer) frequency +#define SYS_TMR_FREQ 1000 + +//-- system timer prescaler +//#define SYS_TMR_PRESCALER T5_PS_1_8 +#define SYS_TMR_PRESCALER_VALUE 64 +#define SYS_TMR_PRESCALER_REGVALUE 2 + +//-- system timer period (auto-calculated) +#define SYS_TMR_PERIOD \ + (PB_FREQ / SYS_TMR_PRESCALER_VALUE / SYS_TMR_FREQ) + + + + +//-- idle task stack size, in words +#define IDLE_TASK_STACK_SIZE (TN_MIN_STACK_SIZE + 16) + +//-- interrupt stack size, in words +#define INTERRUPT_STACK_SIZE (TN_MIN_STACK_SIZE + 64) + + + +/******************************************************************************* + * EXTERN FUNCTION PROTOTYPE + ******************************************************************************/ + +//-- defined by particular example: create first application task(s) +extern void init_task_create(void); + + + +/******************************************************************************* + * DATA + ******************************************************************************/ + +//-- Allocate arrays for stacks: stack for idle task +// and for interrupts are the requirement of the kernel; +// others are application-dependent. +// +// We use convenience macro TN_STACK_ARR_DEF() for that. + +TN_STACK_ARR_DEF(idle_task_stack, IDLE_TASK_STACK_SIZE); +TN_STACK_ARR_DEF(interrupt_stack, INTERRUPT_STACK_SIZE); + + + +/******************************************************************************* + * ISRs + ******************************************************************************/ + +/** + * system timer ISR + */ +tn_p24_soft_isr(_T1Interrupt, auto_psv) +{ + //-- clear interrupt flag + TN_BFA(TN_BFA_WR, IFS0, T1IF, 0); + + //-- proceed system tick + tn_tick_int_processing(); +} + + + +/******************************************************************************* + * FUNCTIONS + ******************************************************************************/ + +/** + * Hardware init: called from main() with interrupts disabled + */ +void hw_init(void) +{ + //-- set up timer1 + TN_BFA(TN_BFA_WR, T1CON, TCS, 0); + TN_BFA(TN_BFA_WR, T1CON, TGATE, 0); + TN_BFA(TN_BFA_WR, T1CON, TSIDL, 1); + + //-- set prescaler: 1:64 + TN_BFA(TN_BFA_WR, T1CON, TCKPS, SYS_TMR_PRESCALER_REGVALUE); + //-- set period + PR1 = (SYS_TMR_PERIOD - 1); + + //-- set timer1 interrupt + TN_BFA(TN_BFA_WR, IPC0, T1IP, 2); //-- set timer1 interrupt priority: 2 + TN_BFA(TN_BFA_WR, IFS0, T1IF, 0); //-- clear interrupt flag + TN_BFA(TN_BFA_WR, IEC0, T1IE, 1); //-- enable interrupt + + //-- eventually, turn the timer on + TN_BFA(TN_BFA_WR, T1CON, TON, 1); +} + +//-- idle callback that is called periodically from idle task +void idle_task_callback (void) +{ +} + +int main(void) +{ + //-- unconditionally disable system interrupts + tn_arch_int_dis(); + + //-- init hardware + hw_init(); + + //-- call to tn_sys_start() never returns + tn_sys_start( + idle_task_stack, + IDLE_TASK_STACK_SIZE, + interrupt_stack, + INTERRUPT_STACK_SIZE, + init_task_create, + idle_task_callback + ); + + //-- unreachable + return 1; +} + +/******************************************************************************* + * ERROR TRAPS + ******************************************************************************/ + +void __attribute((__interrupt__, auto_psv)) _AddressError (void) +{ + SOFTWARE_BREAK(); + //for(;;); +} + +void __attribute((__interrupt__, auto_psv)) _StackError (void) +{ + SOFTWARE_BREAK(); + //for(;;); +} + +void __attribute((__interrupt__, auto_psv)) _MathError (void) +{ + SOFTWARE_BREAK(); + //for(;;); +} + +void __attribute((__interrupt__, auto_psv)) _OscillatorFail (void) +{ + SOFTWARE_BREAK(); + //for(;;); +} + +void __attribute((__interrupt__, auto_psv)) _DefaultInterrupt (void) +{ + SOFTWARE_BREAK(); + //for(;;); +} + + diff --git a/examples/queue/arch/pic24/example_queue_pic24.X/Makefile b/examples/queue/arch/pic24/example_queue_pic24.X/Makefile new file mode 100644 index 0000000..fca8e2c --- /dev/null +++ b/examples/queue/arch/pic24/example_queue_pic24.X/Makefile @@ -0,0 +1,113 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... +# WARNING: the IDE does not call this target since it takes a long time to +# simply run make. Instead, the IDE removes the configuration directories +# under build and dist directly without calling make. +# This target is left here so people can do a clean when running a clean +# outside the IDE. + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml new file mode 100644 index 0000000..7a77efc --- /dev/null +++ b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml @@ -0,0 +1,389 @@ + + + + + + + + + + ../queue_example_arch.c + ../pic24_arch.c + + ../../../queue_example.c + ../../../task_consumer.c + ../../../task_producer.c + + + Makefile + + + + ../../../../common/queue + ../../../../../src/arch/pic32 + ../../.. + + Makefile + + + + localhost + PIC24FJ256GB106 + + + ICD3PlatformTool + XC16 + 1.23 + 2 + + + + + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/project.properties b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/project.properties new file mode 100644 index 0000000..e69de29 diff --git a/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/project.xml b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/project.xml new file mode 100644 index 0000000..3aec5ac --- /dev/null +++ b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/project.xml @@ -0,0 +1,18 @@ + + com.microchip.mplab.nbide.embedded.makeproject + + + example_queue_pic24 + e6b3e7cb-7b49-4750-89c9-cf229d92ec7f + 0 + c + + + + UTF-8 + + ../../../../../src/arch/pic24_dspic/tneokernel_pic24_dspic.X + + + + diff --git a/examples/queue/arch/pic24/pic24_arch.c b/examples/queue/arch/pic24/pic24_arch.c new file mode 100644 index 0000000..84436e7 --- /dev/null +++ b/examples/queue/arch/pic24/pic24_arch.c @@ -0,0 +1,4 @@ + +//-- Include common pic24/dspic source for all examples +#include "../../../common/arch/pic24/pic24_arch.c" + diff --git a/examples/queue/arch/pic24/queue_example_arch.c b/examples/queue/arch/pic24/queue_example_arch.c new file mode 100644 index 0000000..d96e667 --- /dev/null +++ b/examples/queue/arch/pic24/queue_example_arch.c @@ -0,0 +1,63 @@ +/** + * \file + * + * Data queue usage example. + * + * For general information about the pattern, refer to the top of + * queue_example.h file + */ + + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include +#include "tn.h" +#include "queue_example_arch.h" +#include "task_consumer.h" + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PRIVATE DATA + ******************************************************************************/ + +/******************************************************************************* + * PRIVATE FUNCTIONS + ******************************************************************************/ + +/******************************************************************************* + * PUBLIC FUNCTIONS + ******************************************************************************/ + +/** + * See comments in the header file + */ +void queue_example_arch_init(void) +{ + //-- set output for needed pins + TN_BFA(TN_BFA_WR, TRISE, TRISE0, 0); + TN_BFA(TN_BFA_WR, TRISE, TRISE1, 0); + TN_BFA(TN_BFA_WR, TRISE, TRISE2, 0); + + //-- clear current port value + TN_BFA(TN_BFA_WR, LATE, LATE0, 0); + TN_BFA(TN_BFA_WR, LATE, LATE1, 0); + TN_BFA(TN_BFA_WR, LATE, LATE2, 0); +} + +/** + * See comments in the header file + */ +void queue_example_arch_pins_toggle(int pin_mask) +{ + LATE ^= pin_mask; +} + + diff --git a/examples/queue/arch/pic24/queue_example_arch.h b/examples/queue/arch/pic24/queue_example_arch.h new file mode 100644 index 0000000..3aa5e49 --- /dev/null +++ b/examples/queue/arch/pic24/queue_example_arch.h @@ -0,0 +1,15 @@ + +#ifndef _QUEUE_EXAMPLE_ARCH_H +#define _QUEUE_EXAMPLE_ARCH_H + + + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +//-- Include common pic24 header for all examples +#include "../../../common/arch/pic24/example_arch.h" + +#endif // _QUEUE_EXAMPLE_ARCH_H + diff --git a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml index 23647c6..78e80ca 100644 --- a/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml +++ b/examples/queue/arch/pic32/example_queue_pic32.X/nbproject/configurations.xml @@ -92,7 +92,7 @@ + value="..;../../..;../../../../../src"/> @@ -187,8 +187,10 @@ + + @@ -231,12 +233,14 @@ + + @@ -245,6 +249,7 @@ + diff --git a/examples/queue/arch/pic32/queue_example_arch.h b/examples/queue/arch/pic32/queue_example_arch.h index b3ee7a9..6cde6f9 100644 --- a/examples/queue/arch/pic32/queue_example_arch.h +++ b/examples/queue/arch/pic32/queue_example_arch.h @@ -11,16 +11,5 @@ //-- Include common pic32 header for all examples #include "../../../common/arch/pic32/example_arch.h" -/** - * At least, we need to initialize GPIO pins here - */ -void queue_example_arch_init(void); - -/** - * Toggle pins specified by pin_mask - */ -void queue_example_arch_pins_toggle(int pin_mask); - - #endif // _QUEUE_EXAMPLE_ARCH_H diff --git a/examples/queue/queue_example.h b/examples/queue/queue_example.h index c45f248..86a8f40 100644 --- a/examples/queue/queue_example.h +++ b/examples/queue/queue_example.h @@ -136,6 +136,22 @@ void queue_example_init(void); */ struct TN_EventGrp *queue_example_eventgrp_get(void); + + +/** + * Architecture-dependent: + * At least, we need to initialize GPIO pins here + */ +void queue_example_arch_init(void); + +/** + * Architecture-dependent: + * Toggle pins specified by pin_mask + */ +void queue_example_arch_pins_toggle(int pin_mask); + + + #endif // _QUEUE_EXAMPLE_H From e938a01480d6d3ee62c3a52a32c317eda11e1e72 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 01:36:30 +0300 Subject: [PATCH 85/96] pic24: added macro TN_BFAR(), it is used in the queue_example --- .../queue/arch/pic24/queue_example_arch.c | 2 +- src/arch/pic24_dspic/tn_arch_pic24.h | 20 +- src/arch/pic24_dspic/tn_arch_pic24_bfa.h | 202 +++++++++++++----- stuff/doc_pages/pic24_details.dox | 4 +- 4 files changed, 167 insertions(+), 61 deletions(-) diff --git a/examples/queue/arch/pic24/queue_example_arch.c b/examples/queue/arch/pic24/queue_example_arch.c index d96e667..c41cf90 100644 --- a/examples/queue/arch/pic24/queue_example_arch.c +++ b/examples/queue/arch/pic24/queue_example_arch.c @@ -57,7 +57,7 @@ void queue_example_arch_init(void) */ void queue_example_arch_pins_toggle(int pin_mask) { - LATE ^= pin_mask; + TN_BFAR(TN_BFA_INV, LATE, 0, 2, pin_mask); } diff --git a/src/arch/pic24_dspic/tn_arch_pic24.h b/src/arch/pic24_dspic/tn_arch_pic24.h index f6b1e93..462eb27 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24.h +++ b/src/arch/pic24_dspic/tn_arch_pic24.h @@ -38,12 +38,12 @@ * * \file * - * PIC32 architecture-dependent routines + * PIC24/dsPIC architecture-dependent routines * */ -#ifndef _TN_ARCH_PIC32_H -#define _TN_ARCH_PIC32_H +#ifndef _TN_ARCH_PIC24_H +#define _TN_ARCH_PIC24_H #include "../../core/tn_cfg_dispatch.h" @@ -57,17 +57,17 @@ extern "C" { /*}*/ #ifndef DOXYGEN_SHOULD_SKIP_THIS -#define _TN_PIC32_INTSAVE_DATA_INVALID 0xffff +#define _TN_PIC24_INTSAVE_DATA_INVALID 0xffff #if TN_DEBUG -# define _TN_PIC32_INTSAVE_CHECK() \ +# define _TN_PIC24_INTSAVE_CHECK() \ { \ - if (tn_save_status_reg == _TN_PIC32_INTSAVE_DATA_INVALID){ \ + if (tn_save_status_reg == _TN_PIC24_INTSAVE_DATA_INVALID){ \ _TN_FATAL_ERROR(""); \ } \ } #else -# define _TN_PIC32_INTSAVE_CHECK() /* nothing */ +# define _TN_PIC24_INTSAVE_CHECK() /* nothing */ #endif /** @@ -191,7 +191,7 @@ typedef unsigned int TN_UIntPtr; * @see `TN_INT_RESTORE()` */ #define TN_INTSAVE_DATA \ - int tn_save_status_reg = _TN_PIC32_INTSAVE_DATA_INVALID; + int tn_save_status_reg = _TN_PIC24_INTSAVE_DATA_INVALID; /** * The same as `#TN_INTSAVE_DATA` but for using in ISR together with @@ -229,7 +229,7 @@ typedef unsigned int TN_UIntPtr; */ # define TN_INT_DIS_SAVE() tn_save_status_reg = tn_arch_sr_save_int_dis() -# define TN_INT_RESTORE() _TN_PIC32_INTSAVE_CHECK(); \ +# define TN_INT_RESTORE() _TN_PIC24_INTSAVE_CHECK(); \ tn_arch_sr_restore(tn_save_status_reg) /** @@ -456,5 +456,5 @@ typedef unsigned int TN_UIntPtr; } /* extern "C" */ #endif -#endif // _TN_ARCH_PIC32_H +#endif // _TN_ARCH_PIC24_H diff --git a/src/arch/pic24_dspic/tn_arch_pic24_bfa.h b/src/arch/pic24_dspic/tn_arch_pic24_bfa.h index bbc0132..730633b 100644 --- a/src/arch/pic24_dspic/tn_arch_pic24_bfa.h +++ b/src/arch/pic24_dspic/tn_arch_pic24_bfa.h @@ -73,64 +73,22 @@ extern "C" { /*}*/ /// /// Command for `TN_BFA()` macro: Set bits in the bit field by mask; /// `...` macro param should be set to the bit mask to set. -/// -/// Example: -/// \code{.c} -/// //-- Set third bit of the INT0IP field in the IPC0 register: -/// // IPC0bits.INT0IP |= (1 << 2); -/// TN_BFA(TN_BFA_SET, IPC0, INT0IP, (1 << 2)); -/// \endcode #define TN_BFA_SET 0x1111 /// /// Command for `TN_BFA()` macro: Clear bits in the bit field by mask; /// `...` macro param should be set to the bit mask to clear. -/// -/// Example: -/// \code{.c} -/// //-- Clear second bit of the INT0IP field in the IPC0 register: -/// // IPC0bits.INT0IP &= ~(1 << 1); -/// TN_BFA(TN_BFA_CLR, IPC0, INT0IP, (1 << 1)); -/// \endcode #define TN_BFA_CLR 0x2222 /// /// Command for `TN_BFA()` macro: Invert bits in the bit field by mask; /// `...` macro param should be set to the bit mask to invert. -/// -/// Example: -/// \code{.c} -/// //-- Invert two less-significant bits of the INT0IP field -/// // in the IPC0 register: -/// // IPC0bits.INT0IP ^= 0x03; -/// TN_BFA(TN_BFA_INV, IPC0, INT0IP, 0x03); -/// \endcode #define TN_BFA_INV 0x3333 /// /// Command for `TN_BFA()` macro: Write bit field; /// `...` macro param should be set to the value to write. -/// -/// Example: -/// \code{.c} -/// //-- Write value 0x05 to the INT0IP field of the IPC0 register: -/// // IPC0bits.INT0IP = 0x05; -/// TN_BFA(TN_BFA_WR, IPC0, INT0IP, 0x05); -/// -/// //-- Write value of the variable a to the INT0IP field of the IPC0 -/// // register: -/// // IPC0bits.INT0IP = a; -/// TN_BFA(TN_BFA_WR, IPC0, INT0IP, a); -/// \endcode #define TN_BFA_WR 0xAAAA /// /// Command for `TN_BFA()` macro: Read bit field; /// `...` macro param ignored. -/// -/// Example: -/// \code{.c} -/// //-- Read the value that is stored in the INT0IP field of the IPC0 -/// // register, to the int variable a: -/// // int a = IPC0bits.INT0IP; -/// int a = TN_BFA(TN_BFA_RD, IPC0, INT0IP); -/// \endcode #define TN_BFA_RD 0xBBBB @@ -143,9 +101,9 @@ extern "C" { /*}*/ * command to execute: * - `#TN_BFA_WR` - write bit field * - `#TN_BFA_RD` - read bit field - * - `#TN_BFA_SET` - set bit fields by mask - * - `#TN_BFA_CLR` - clear bit fields by mask - * - `#TN_BFA_INV` - invert bit fields by mask + * - `#TN_BFA_SET` - set bits by mask + * - `#TN_BFA_CLR` - clear bits by mask + * - `#TN_BFA_INV` - invert bits by mask * * @param reg_name * register name (`PORTA`, `CMCON`, ...). @@ -154,10 +112,44 @@ extern "C" { /*}*/ * structure field name * * @param ... - * used if only `comm != #TN_BFA_RD`. Should be equal to the value to - * write to field. You can use variable here. + * used if only `comm != #TN_BFA_RD`. Meaning depends on the `comm`, + * see comments for specific command: `#TN_BFA_WR`, etc. * - * See usage examples for each of the commands: `#TN_BFA_WR`, etc. + * + * Usage examples: + * + * \code{.c} + * + * int a = 0x02; + * + * //-- Set third bit of the INT0IP field in the IPC0 register: + * // IPC0bits.INT0IP |= (1 << 2); + * TN_BFA(TN_BFA_SET, IPC0, INT0IP, (1 << 2)); + * + * //-- Clear second bit of the INT0IP field in the IPC0 register: + * // IPC0bits.INT0IP &= ~(1 << 1); + * TN_BFA(TN_BFA_CLR, IPC0, INT0IP, (1 << 1)); + * + * //-- Invert two less-significant bits of the INT0IP field + * // in the IPC0 register: + * // IPC0bits.INT0IP ^= 0x03; + * TN_BFA(TN_BFA_INV, IPC0, INT0IP, 0x03); + * + * //-- Write value 0x05 to the INT0IP field of the IPC0 register: + * // IPC0bits.INT0IP = 0x05; + * TN_BFA(TN_BFA_WR, IPC0, INT0IP, 0x05); + * + * //-- Write value of the variable a to the INT0IP field of the IPC0 + * // register: + * // IPC0bits.INT0IP = a; + * TN_BFA(TN_BFA_WR, IPC0, INT0IP, a); + * + * //-- Read the value that is stored in the INT0IP field of the IPC0 + * // register, to the int variable a: + * // int a = IPC0bits.INT0IP; + * a = TN_BFA(TN_BFA_RD, IPC0, INT0IP); + * + * \endcode */ #define TN_BFA(comm, reg_name, field_name, ...) \ ({ \ @@ -228,6 +220,120 @@ extern "C" { /*}*/ +/** + * Macro for atomic access to the structure bit field specified as a range. + * + * @param comm + * command to execute: + * - `#TN_BFA_WR` - write bit field + * - `#TN_BFA_RD` - read bit field + * - `#TN_BFA_SET` - set bits by mask + * - `#TN_BFA_CLR` - clear bits by mask + * - `#TN_BFA_INV` - invert bits by mask + * + * @param reg_name + * variable name (`PORTA`, `CMCON`, ...). Variable should be in the near + * memory (first 8 KB) + * + * @param lower + * number of lowest affected bit of the field + * + * @param upper + * number of highest affected bit of the field + * + * @param ... + * used if only `comm != #TN_BFA_RD`. Meaning depends on the `comm`, + * see comments for specific command: `#TN_BFA_WR`, etc. + * + * + * Usage examples: + * + * \code{.c} + * + * int a = 0x02; + * + * //-- Write constant 0xaa to the least significant byte of the TRISB + * // register: + * TN_BFAR(TN_BFA_WR, TRISB, 0, 7, 0xaa); + * + * //-- Invert least significant nibble of the most significant byte + * // in the register TRISB: + * TN_BFAR(TN_BFA_INV, TRISB, 8, 15, 0x0f); + * + * //-- Get 5 least significant bits from the register TRISB and store + * // result to the variable a + * a = TN_BFAR(TN_BFA_RD, TRISB, 0, 4); + * + * \endcode + * + */ +#define TN_BFAR(comm, reg_name, lower, upper, ...) \ + ({ \ + unsigned int lmask, lmaskl, lmasku; \ + lmaskl = (1 << (lower)); \ + lmasku = (1 << (upper)); \ + lmask = ((lmaskl-1) ^ (lmasku-1)) | lmaskl | lmasku; \ + ((comm) == TN_BFA_WR) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + v = (v << (((lower) < (upper)) ? (lower) : (upper))) & lmask; \ + __asm__ __volatile__ \ + (" xor %0": "=T"(reg_name):"a"(lmask & (v ^ reg_name))); \ + }), 0 \ + :(((comm) == TN_BFA_INV) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask & (lmask-1)) \ + { \ + v = (v << (((lower) < (upper)) ? (lower) : (upper))) & lmask; \ + __asm__ __volatile__( \ + " xor %0":"=T"(reg_name):"a"(lmask & v)); \ + } else { \ + if (v & 1) \ + __asm__ __volatile__( \ + " btg %0, #%1" :"=T"(reg_name) :"i"(lower)); \ + } \ + }), 0 \ + \ + :(((comm) == TN_BFA_SET) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask & (lmask-1)) \ + { \ + v = (v << (((lower) < (upper)) ? (lower) : (upper))) & lmask; \ + __asm__ __volatile__(" ior %0 " \ + :"=T"(reg_name) \ + :"a"(lmask & v)); \ + } else { \ + if (v & 1) \ + __asm__ __volatile__( \ + " bset %0, #%1" :"=T"(reg_name) :"i"(lower)); \ + } \ + }), 0 \ + \ + :((((comm) == TN_BFA_CLR) \ + ?({ \ + _TN_BFA_COMM_GET(comm) v = __VA_ARGS__+0; \ + if (lmask & (lmask-1)) \ + { \ + v = (v << (((lower) < (upper)) ? (lower) : (upper))) & lmask; \ + __asm__ __volatile__(" and %0 " \ + :"=T"(reg_name) \ + :"a"(~(lmask & v))); \ + } else { \ + if (v & 1) \ + __asm__ __volatile__( \ + " bclr %0, #%1" :"=T"(reg_name) :"i"(lower)); \ + } \ + }), 0 \ + \ + :({ /* TN_BFA_RD */ \ + (reg_name & lmask) >> (((lower) < (upper)) ? (lower) : (upper)); \ + }))))); \ + }) + + + //-- internal kernel macros {{{ #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/stuff/doc_pages/pic24_details.dox b/stuff/doc_pages/pic24_details.dox index 6f23e63..4acacd4 100644 --- a/stuff/doc_pages/pic24_details.dox +++ b/stuff/doc_pages/pic24_details.dox @@ -79,8 +79,8 @@ IPC0bits.INT0IP = 0x05; \endcode We actually have read-modify-write sequence which can be interrupted, so that -resulting data could be corrupted. PIC24/dsPIC port provides `TN_BFA()` macro -that provides atomic access to the structure bit field. +resulting data could be corrupted. PIC24/dsPIC port provides several macros +that offer atomic access to the structure bit field. The kernel would not probably provide that kind of functionality, but TNeoKernel itself needs it, so, it is made public so that application can From 503cae4adc635f920d21d59ee7f0d314f76b8827 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 01:45:15 +0300 Subject: [PATCH 86/96] refactor: things renamed in example_queue_eventgrp_conn --- ...h.c => example_queue_eventgrp_conn_arch.c} | 7 ++-- .../pic32/example_queue_eventgrp_conn_arch.h | 15 ++++++++ .../nbproject/configurations.xml | 4 +-- .../arch/pic32/queue_example_arch.h | 36 ------------------- ...xample.c => example_queue_eventgrp_conn.c} | 2 +- ...xample.h => example_queue_eventgrp_conn.h} | 36 ++++++++++++++++--- examples/queue_eventgrp_conn/task_consumer.c | 2 +- examples/queue_eventgrp_conn/task_producer.c | 2 +- 8 files changed, 55 insertions(+), 49 deletions(-) rename examples/queue_eventgrp_conn/arch/pic32/{queue_example_arch.c => example_queue_eventgrp_conn_arch.c} (89%) create mode 100644 examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_arch.h delete mode 100644 examples/queue_eventgrp_conn/arch/pic32/queue_example_arch.h rename examples/queue_eventgrp_conn/{queue_example.c => example_queue_eventgrp_conn.c} (93%) rename examples/queue_eventgrp_conn/{queue_example.h => example_queue_eventgrp_conn.h} (85%) diff --git a/examples/queue_eventgrp_conn/arch/pic32/queue_example_arch.c b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_arch.c similarity index 89% rename from examples/queue_eventgrp_conn/arch/pic32/queue_example_arch.c rename to examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_arch.c index d6bb138..9a00d95 100644 --- a/examples/queue_eventgrp_conn/arch/pic32/queue_example_arch.c +++ b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_arch.c @@ -1,10 +1,9 @@ /** * \file * - * Data queue usage example. + * Usage example of connecting event group to other kernel objects. + * Refer to the readme.txt file for details. * - * For general information about the pattern, refer to the top of - * queue_example.h file */ @@ -13,7 +12,7 @@ ******************************************************************************/ #include -#include "queue_example_arch.h" +#include "example_queue_eventgrp_conn_arch.h" #include "task_consumer.h" diff --git a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_arch.h b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_arch.h new file mode 100644 index 0000000..f729ddf --- /dev/null +++ b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_arch.h @@ -0,0 +1,15 @@ + +#ifndef _EXAMPLE_QUEUE_EVENTGRP_CONN_ARCH_H +#define _EXAMPLE_QUEUE_EVENTGRP_CONN_ARCH_H + + + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +//-- Include common pic32 header for all examples +#include "../../../common/arch/pic32/example_arch.h" + +#endif // _EXAMPLE_QUEUE_EVENTGRP_CONN_ARCH_H + diff --git a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml index 4081037..04424c3 100644 --- a/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml +++ b/examples/queue_eventgrp_conn/arch/pic32/example_queue_eventgrp_conn_pic32.X/nbproject/configurations.xml @@ -14,12 +14,12 @@ projectFiles="true"> ../pic32_arch.c - ../queue_example_arch.c ../../../../../src/arch/pic32/tn_arch_pic32_int_vec1.S + ../example_queue_eventgrp_conn_arch.c - ../../../queue_example.c ../../../task_consumer.c ../../../task_producer.c + ../../../example_queue_eventgrp_conn.c Date: Tue, 4 Nov 2014 01:47:51 +0300 Subject: [PATCH 87/96] pic24: queue_example project settings altered (optimization, etc) --- .../nbproject/configurations.xml | 114 +----------------- 1 file changed, 2 insertions(+), 112 deletions(-) diff --git a/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml index 7a77efc..c2dbfcf 100644 --- a/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml +++ b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml @@ -115,7 +115,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -201,116 +201,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From b868147acd617e8f6831a288fe77f349f0d98e84 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 01:57:24 +0300 Subject: [PATCH 88/96] pic24: example_queue_eventgrp_conn is implemented --- .../pic24/example_queue_eventgrp_conn_arch.c | 74 +++++ .../pic24/example_queue_eventgrp_conn_arch.h | 15 + .../Makefile | 113 ++++++++ .../nbproject/configurations.xml | 260 ++++++++++++++++++ .../nbproject/project.properties | 0 .../nbproject/project.xml | 18 ++ .../arch/pic24/pic24_arch.c | 4 + 7 files changed, 484 insertions(+) create mode 100644 examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.c create mode 100644 examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.h create mode 100644 examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/Makefile create mode 100644 examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml create mode 100644 examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/project.properties create mode 100644 examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/project.xml create mode 100644 examples/queue_eventgrp_conn/arch/pic24/pic24_arch.c diff --git a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.c b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.c new file mode 100644 index 0000000..a0ca2ed --- /dev/null +++ b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.c @@ -0,0 +1,74 @@ +/** + * \file + * + * Usage example of connecting event group to other kernel objects. + * Refer to the readme.txt file for details. + * + */ + + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +#include +#include "tn.h" +#include "example_queue_eventgrp_conn_arch.h" +#include "task_consumer.h" + + + +/******************************************************************************* + * DEFINITIONS + ******************************************************************************/ + + +/******************************************************************************* + * PRIVATE DATA + ******************************************************************************/ + +/******************************************************************************* + * PRIVATE FUNCTIONS + ******************************************************************************/ + +/******************************************************************************* + * PUBLIC FUNCTIONS + ******************************************************************************/ + +/** + * See comments in the header file + */ +void queue_example_arch_init(void) +{ + //-- set output for needed pins + TN_BFAR(TN_BFA_CLR, TRISE, 0, 15, 0x03); + + //-- clear current port value + TN_BFAR(TN_BFA_WR, LATE, 0, 15, 0x03); +} + +/** + * See comments in the header file + */ +void queue_example_arch_pins_toggle(int pin_mask) +{ + TN_BFAR(TN_BFA_INV, LATE, 0, 2, pin_mask); +} + +/** + * See comments in the header file + */ +void queue_example_arch_pins_set(int pin_mask) +{ + TN_BFAR(TN_BFA_SET, LATE, 0, 2, pin_mask); +} + +/** + * See comments in the header file + */ +void queue_example_arch_pins_clear(int pin_mask) +{ + TN_BFAR(TN_BFA_CLR, LATE, 0, 2, pin_mask); +} + + diff --git a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.h b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.h new file mode 100644 index 0000000..299230e --- /dev/null +++ b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_arch.h @@ -0,0 +1,15 @@ + +#ifndef _EXAMPLE_QUEUE_EVENTGRP_CONN_ARCH_H +#define _EXAMPLE_QUEUE_EVENTGRP_CONN_ARCH_H + + + +/******************************************************************************* + * INCLUDED FILES + ******************************************************************************/ + +//-- Include common pic32 header for all examples +#include "../../../common/arch/pic24/example_arch.h" + +#endif // _EXAMPLE_QUEUE_EVENTGRP_CONN_ARCH_H + diff --git a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/Makefile b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/Makefile new file mode 100644 index 0000000..fca8e2c --- /dev/null +++ b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/Makefile @@ -0,0 +1,113 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... +# WARNING: the IDE does not call this target since it takes a long time to +# simply run make. Instead, the IDE removes the configuration directories +# under build and dist directly without calling make. +# This target is left here so people can do a clean when running a clean +# outside the IDE. + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml new file mode 100644 index 0000000..4a92036 --- /dev/null +++ b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml @@ -0,0 +1,260 @@ + + + + + + + + + + ../example_queue_eventgrp_conn_arch.c + ../pic24_arch.c + + ../../../example_queue_eventgrp_conn.c + ../../../task_consumer.c + ../../../task_producer.c + + + Makefile + + + + ../../.. + + Makefile + + + + localhost + PIC24FJ256GB106 + + + ICD3PlatformTool + XC16 + 1.23 + 2 + + + + + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/project.properties b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/project.properties new file mode 100644 index 0000000..e69de29 diff --git a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/project.xml b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/project.xml new file mode 100644 index 0000000..760b391 --- /dev/null +++ b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/project.xml @@ -0,0 +1,18 @@ + + com.microchip.mplab.nbide.embedded.makeproject + + + example_queue_eventgrp_conn_pic24 + e38a54f5-9919-4dc2-b1e1-f130db748458 + 0 + c + + + + UTF-8 + + ../../../../../src/arch/pic24_dspic/tneokernel_pic24_dspic.X + + + + diff --git a/examples/queue_eventgrp_conn/arch/pic24/pic24_arch.c b/examples/queue_eventgrp_conn/arch/pic24/pic24_arch.c new file mode 100644 index 0000000..5e02716 --- /dev/null +++ b/examples/queue_eventgrp_conn/arch/pic24/pic24_arch.c @@ -0,0 +1,4 @@ + +//-- Include common pic32 source for all examples +#include "../../../common/arch/pic24/pic24_arch.c" + From 43c38e69019721c6108ae0a1ae97b369c842091b Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 02:43:58 +0300 Subject: [PATCH 89/96] create_version_archive.sh: added pic24/dspic bin generation --- stuff/doxygen/create_version_archive.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/stuff/doxygen/create_version_archive.sh b/stuff/doxygen/create_version_archive.sh index 335c688..6b1f57b 100644 --- a/stuff/doxygen/create_version_archive.sh +++ b/stuff/doxygen/create_version_archive.sh @@ -45,6 +45,24 @@ popd # }}} +# generate pic24/dspic hex {{{ + +pic24_bin="$tmp_repo_path/bin/pic24_dspic" + +pushd src/arch/pic24_dspic/tneokernel_pic24_dspic.X +make + +# in the target temp dir, create "bin" dir +mkdir -p "$pic24_bin" + +# copy hex there +cp dist/default/production/tneokernel_pic24_dspic.X.a "$pic24_bin" + +# cd back +popd + +# }}} + # cd to temp dir cd $tmp_repo_path From c6c743e1998209be23edb889c1c4f2678b2ffda2 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 03:19:37 +0300 Subject: [PATCH 90/96] pic24: MPLABX project now has two configurations: 'eds' and 'no_eds'; for devices with and without extended data space, respectively. --- .../nbproject/configurations.xml | 62 ++++- .../nbproject/configurations.xml | 20 +- .../nbproject/configurations.xml | 21 +- .../nbproject/configurations.xml | 216 +++++++++++++++++- 4 files changed, 286 insertions(+), 33 deletions(-) diff --git a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml index 3bcc997..4695999 100644 --- a/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml +++ b/examples/basic/arch/pic24/tn_pic24_example_basic.X/nbproject/configurations.xml @@ -36,7 +36,7 @@ ICD3PlatformTool XC16 - 1.21 + 1.23 2 @@ -45,18 +45,18 @@ + BC="${MAKE} -f Makefile CONF=no_eds" + DBC="${MAKE} -f Makefile CONF=no_eds TYPE_IMAGE=DEBUG_RUN" + CC="rm -rf "build/no_eds" "dist/no_eds"" + OP="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + DOP="dist/no_eds/debug/tneokernel_pic24_dspic.X.a" + FL="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + PD="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + DD="dist/no_eds/debug/tneokernel_pic24_dspic.X.a"> @@ -94,11 +94,28 @@ + + + + + + + + + + + + + + + + + @@ -122,6 +139,7 @@ + @@ -132,13 +150,27 @@ + + + + + + + + + + + + + + @@ -152,9 +184,15 @@ + + + + + + @@ -162,6 +200,7 @@ + @@ -185,6 +224,7 @@ + diff --git a/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml index c2dbfcf..3a05fd9 100644 --- a/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml +++ b/examples/queue/arch/pic24/example_queue_pic24.X/nbproject/configurations.xml @@ -50,18 +50,18 @@ + BC="${MAKE} -f Makefile CONF=no_eds" + DBC="${MAKE} -f Makefile CONF=no_eds TYPE_IMAGE=DEBUG_RUN" + CC="rm -rf "build/no_eds" "dist/no_eds"" + OP="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + DOP="dist/no_eds/debug/tneokernel_pic24_dspic.X.a" + FL="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + PD="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + DD="dist/no_eds/debug/tneokernel_pic24_dspic.X.a"> diff --git a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml index 4a92036..31acddc9 100644 --- a/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml +++ b/examples/queue_eventgrp_conn/arch/pic24/example_queue_eventgrp_conn_pic24.X/nbproject/configurations.xml @@ -48,18 +48,18 @@ + BC="${MAKE} -f Makefile CONF=no_eds" + DBC="${MAKE} -f Makefile CONF=no_eds TYPE_IMAGE=DEBUG_RUN" + CC="rm -rf "build/no_eds" "dist/no_eds"" + OP="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + DOP="dist/no_eds/debug/tneokernel_pic24_dspic.X.a" + FL="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + PD="dist/no_eds/production/tneokernel_pic24_dspic.X.a" + DD="dist/no_eds/debug/tneokernel_pic24_dspic.X.a"> @@ -229,6 +229,7 @@ + diff --git a/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml index abeb0e6..1042ae0 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml @@ -40,10 +40,10 @@ Makefile - + localhost - PIC24FJ192GB110 + PIC24FJ256GB106 ICD3PlatformTool @@ -266,5 +266,217 @@ + + + localhost + PIC24FJ256GB206 + + + ICD3PlatformTool + XC16 + 1.23 + 2 + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d41f71cface31a5165dffd5af1b2110e077c031e Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 03:29:22 +0300 Subject: [PATCH 91/96] pic24: docs updated regarding to eds and no_eds configurations --- stuff/doc_pages/building.dox | 19 +++++-------------- stuff/doc_pages/pic24_details.dox | 19 +++++++++++++++++++ stuff/doc_pages/pic32_details.dox | 11 +++++++++++ 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/stuff/doc_pages/building.dox b/stuff/doc_pages/building.dox index bfcbc68..5d21676 100644 --- a/stuff/doc_pages/building.dox +++ b/stuff/doc_pages/building.dox @@ -30,21 +30,12 @@ supports symbolic links, copy it somewhere to your main project's directory Default configuration file contains detailed comments, so you can read them and configure behavior as you like. -\section building_pic32 PIC32 port: MPLABX project +\section building_generic Building the project -MPLABX project resides in the `src/arch/pic32/tneokernel_pic32.X` directory. -This is a *library project* in terms of MPLABX, so if you use MPLABX you can -easily add it to your main project by right-clicking `Libraries -> Add Library -Project ...`. Alternatively, of course you can just build it and use -resulting `tneokernel_pic32.X.a` file in whatever way you like. - -\section building_pic24_dspic PIC24/dsPIC port: MPLABX project - -MPLABX project resides in the `src/arch/pic24_dspic/tneokernel_pic24_dspic.X` -directory. This is a *library project* in terms of MPLABX, so if you use MPLABX -you can easily add it to your main project by right-clicking `Libraries -> Add -Library Project ...`. Alternatively, of course you can just build it and use -resulting `tneokernel_pic24_dspic.X.a` file in whatever way you like. +For information on building TNeoKernel, please refer to the appropriate section +for your platform: +- \ref pic24_building "Building for PIC24/dsPIC" +- \ref pic32_building "Building for PIC32" */ diff --git a/stuff/doc_pages/pic24_details.dox b/stuff/doc_pages/pic24_details.dox index 4acacd4..f86298e 100644 --- a/stuff/doc_pages/pic24_details.dox +++ b/stuff/doc_pages/pic24_details.dox @@ -90,4 +90,23 @@ Refer to the page \ref tn_arch_pic24_bfa.h "Atomic bit-field access macros" for details. +\section pic24_building Building + +For generic information on building TNeoKernel, refer to the page \ref building. + +MPLABX project for PIC24/dsPIC port resides in the +`src/arch/pic24_dspic/tneokernel_pic24_dspic.X` directory. This is a *library +project* in terms of MPLABX, so if you use MPLABX you can easily add it to your +main project by right-clicking `Libraries -> Add Library Project ...`. + +\attention there are two configurations of this project: eds and +no_eds, for devices with and without extended data space, respectively. +When you add library project to your application project, you should select +correct configuration for your device; otherwise, you get "undefined reference" +errors at linker step. + +Alternatively, of course you can just build it and use +resulting `.a` file in whatever way you like. + + */ diff --git a/stuff/doc_pages/pic32_details.dox b/stuff/doc_pages/pic32_details.dox index 1f38924..6614ad9 100644 --- a/stuff/doc_pages/pic32_details.dox +++ b/stuff/doc_pages/pic32_details.dox @@ -91,4 +91,15 @@ consider the following: - Kernel-provided interrupt macro that uses shadow register set saves a little amount of registers **on the interrupt stack**. +\section pic32_building Building + +For generic information on building TNeoKernel, refer to the page \ref building. + +MPLABX project for PIC32 port resides in the +`src/arch/pic32/tneokernel_pic32.X` directory. This is a *library project* in +terms of MPLABX, so if you use MPLABX you can easily add it to your main +project by right-clicking `Libraries -> Add Library Project ...`. +Alternatively, of course you can just build it and use resulting +`tneokernel_pic32.X.a` file in whatever way you like. + */ From 5c3383ec94d606a373814c96315338ea991e9fbd Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 03:34:21 +0300 Subject: [PATCH 92/96] pic24: create_version_archive.sh now creates two binaries: for 'eds' and 'no_eds' configurations --- stuff/doxygen/create_version_archive.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stuff/doxygen/create_version_archive.sh b/stuff/doxygen/create_version_archive.sh index 6b1f57b..5c89d9c 100644 --- a/stuff/doxygen/create_version_archive.sh +++ b/stuff/doxygen/create_version_archive.sh @@ -50,13 +50,14 @@ popd pic24_bin="$tmp_repo_path/bin/pic24_dspic" pushd src/arch/pic24_dspic/tneokernel_pic24_dspic.X -make +make all # in the target temp dir, create "bin" dir mkdir -p "$pic24_bin" # copy hex there -cp dist/default/production/tneokernel_pic24_dspic.X.a "$pic24_bin" +cp dist/eds/production/tneokernel_pic24_dspic.X.a "$pic24_bin/tneokernel_pic24_dspic_eds.X.a" +cp dist/no_eds/production/tneokernel_pic24_dspic.X.a "$pic24_bin/tneokernel_pic24_dspic_no_eds.X.a" # cd back popd From fc167a498f96e649fc12b3884e86576a878c1ae2 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 03:37:38 +0300 Subject: [PATCH 93/96] little change in comments --- stuff/doxygen/create_version_archive.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stuff/doxygen/create_version_archive.sh b/stuff/doxygen/create_version_archive.sh index 5c89d9c..32a765c 100644 --- a/stuff/doxygen/create_version_archive.sh +++ b/stuff/doxygen/create_version_archive.sh @@ -27,7 +27,7 @@ fi # clone it from the current one hg clone $repo_path $tmp_repo_path -# generate pic32 hex {{{ +# generate pic32 binary {{{ pic32_bin="$tmp_repo_path/bin/pic32" @@ -37,7 +37,7 @@ make # in the target temp dir, create "bin" dir mkdir -p "$pic32_bin" -# copy hex there +# copy binary there cp dist/default/production/tneokernel_pic32.X.a "$pic32_bin" # cd back @@ -45,7 +45,7 @@ popd # }}} -# generate pic24/dspic hex {{{ +# generate pic24/dspic binaries {{{ pic24_bin="$tmp_repo_path/bin/pic24_dspic" @@ -55,7 +55,7 @@ make all # in the target temp dir, create "bin" dir mkdir -p "$pic24_bin" -# copy hex there +# copy binaries there cp dist/eds/production/tneokernel_pic24_dspic.X.a "$pic24_bin/tneokernel_pic24_dspic_eds.X.a" cp dist/no_eds/production/tneokernel_pic24_dspic.X.a "$pic24_bin/tneokernel_pic24_dspic_no_eds.X.a" From c5d7e778abde69eb4f9e10c994f733b35e80d2db Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 03:45:30 +0300 Subject: [PATCH 94/96] MPLABX automatic project change --- .../nbproject/configurations.xml | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml index 1042ae0..575b892 100644 --- a/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml +++ b/src/arch/pic24_dspic/tneokernel_pic24_dspic.X/nbproject/configurations.xml @@ -421,24 +421,37 @@ + + + + + + + - - + + + + + + + + @@ -450,6 +463,9 @@ + + + From 52d3179c29d29029caa60da04891fed545695c13 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 04:21:56 +0300 Subject: [PATCH 95/96] readme updated: PIC24/dsPIC port is moved out of beta --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e0642c..69a70eb 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ round-robin scheduling for the tasks with identical priority. TNeoKernel was born as a thorough review and re-implementation of [TNKernel](http://tnkernel.com) v2.7. The new kernel has well-formed code, inherited bugs are fixed as well as new features being added, it is well documented and tested carefully with unit-tests. -Currently it is available for PIC32 (PIC24/dsPIC is also supported in BETA), and it will be ported at least to ARM Cortex M3. +Currently it is available for PIC32/PIC24/dsPIC, and it will be ported at least to ARM Cortex M3 in a few months. Comprehensive documentation is available in two forms: html and pdf. From 2ac13dad7475a89b8ae5f6177eb55d9e8dbfcc60 Mon Sep 17 00:00:00 2001 From: Dmitry Frank Date: Tue, 4 Nov 2014 04:25:31 +0300 Subject: [PATCH 96/96] changelog is updated for release v1.04 --- stuff/doc_pages/changelog.dox | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stuff/doc_pages/changelog.dox b/stuff/doc_pages/changelog.dox index b5e9487..ebf7993 100644 --- a/stuff/doc_pages/changelog.dox +++ b/stuff/doc_pages/changelog.dox @@ -5,7 +5,9 @@ TNeoKernel changelog -\section changelog_current Current development version (BETA) +\section changelog_v1_04 v1.04 + +Release date: 2014-11-04. - Added PIC24/dsPIC support, refer to the page \ref pic24_details; - PIC32: Core Software Interrupt is now handled by the kernel completely,