Merge pull request #2804 from yogpan01/mbed-os.5.2-rc1

Updating mbed-client-c and sal-stack-nanostack-eventloop
pull/2809/head
Sam Grove 2016-09-25 22:11:24 -05:00 committed by GitHub
commit 98030475af
35 changed files with 514 additions and 1146 deletions

View File

@ -1,5 +1,131 @@
# Change Log
## [v3.0.2](https://github.com/ARMmbed/mbed-client-c/releases/tag/v3.0.2) (24-Sep-2016)
[Full Changelog](https://github.com/ARMmbed/mbed-client-c/compare/v3.0.1...v3.0.2)
**New feature**
- Make resending flags configurable through Yotta and mbed-cli build systems
- Introducing Configuration management through Config file
**Closed issues:**
- IOTCLT-882 - Confirmable messages sending
**Merged pull requests:**
commit 58f712b9f684bede1905ce35a1a39ebb257c049c (HEAD, tag: v3.0.2, origin/master, origin/HEAD, master)
Author: Yogesh Pande <Yogesh.Pande@arm.com>
Date: Sat Sep 24 15:04:36 2016 +0300
version v3.0.2
commit 39d5e98025f3d8067cea85c4a06470e0e9374812
Merge: cf4c119 31d6566
Author: Yogesh Pande <yogpan01@users.noreply.github.com>
Date: Sat Sep 24 14:51:30 2016 +0300
Merge pull request #79 from ARMmbed/config-mechanism
Introducing Configuration management through Config file
commit 31d6566dddfe449e87819244027b847f53f53a96 (origin/config-mechanism)
Author: Yogesh Pande <Yogesh.Pande@arm.com>
Date: Sat Sep 24 12:53:47 2016 +0300
Fixing valgrind with unit tests
commit a95a90a31e8f6123d14df84688b4e2e2f32e5507
Author: Yogesh Pande <Yogesh.Pande@arm.com>
Date: Sat Sep 24 12:00:44 2016 +0300
Fixing valgrind memory leaks for unit tests
commit 248fc713a4303cb1f724d10f4aa6d68933bb5aed
Author: Yogesh Pande <Yogesh.Pande@arm.com>
Date: Sat Sep 24 11:32:01 2016 +0300
Fix for failing unit tests
commit cec0980b4ccff9708cd0130fea936a69839739b8
Merge: cf09b2b cf4c119
Author: Yogesh Pande <yogpan01@users.noreply.github.com>
Date: Thu Sep 22 18:02:39 2016 +0300
Merge branch 'master' into config-mechanism
commit cf4c1196520d64bf863b39efefc663ee60e58c61
Merge: 330a16b f5f15cc
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Thu Sep 22 12:55:33 2016 +0300
Merge pull request #80 from ARMmbed/revert-77-duplication
Revert "Enable message duplication by default"
commit f5f15ccce5fd719aa8d7de14a583d02fd0fd05b9 (origin/revert-77-duplication)
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Thu Sep 22 12:30:50 2016 +0300
Revert "Enable message duplication by default"
commit cf09b2b6233bf897a17bdb0102962947df87f4ae
Author: Yogesh Pande <Yogesh.Pande@arm.com>
Date: Thu Sep 22 09:57:41 2016 +0300
Fixed comments from PR#79
This commit includes
- Fixing comments from PR-79
commit 8fd7cc258168047c29aca27a659de448f45e0e6f
Author: Yogesh Pande <Yogesh.Pande@arm.com>
Date: Wed Sep 21 20:42:28 2016 +0300
Introducing Configuration management through Config file
This commit includes
- Support for configuring various build time parameters throuh user supplied config file
that can be passed at compile time through Makefile system which will work for
non mbed-OS and non yotta build system as well.
commit 330a16bbfc5dc597015c7bdd935b603282d7064e
Merge: b7d909e e268081
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Wed Sep 21 12:05:29 2016 +0300
Merge pull request #78 from ARMmbed/resend_flags
Make resend flags configurable through Yotta and mbed-cli build sy…
commit e268081bae1fa1db3b5b64dfb77d5b7a5bfed748
Merge: dc16b29 b7d909e
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Wed Sep 21 12:02:32 2016 +0300
Merge branch 'master' into resend_flags
commit b7d909eca1c2259453dbe9c094b8a0c53d638fea
Merge: 7f0eaea ad3b468
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Wed Sep 21 12:02:15 2016 +0300
Merge pull request #77 from ARMmbed/duplication
Enable message duplication by default
commit dc16b299ab9ff4bd1eaa9d3ec120fa58180820c4
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Mon Sep 19 14:35:31 2016 +0300
Make resending flags configurable through Yotta and mbed-cli build systems
commit ad3b46881bb61dfc2510d13d373bcd1faad114f4
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Fri Sep 16 08:58:38 2016 +0300
Enable message duplication by default
## [v3.0.1](https://github.com/ARMmbed/mbed-client-c/releases/tag/v3.0.1) (15-Sep-2016)
[Full Changelog](https://github.com/ARMmbed/mbed-client-c/compare/mbed-os-5.0-rc1...v3.0.1)

View File

@ -1,6 +1,6 @@
{
"name": "mbed-client-c",
"version": "3.0.1",
"version": "3.0.2",
"description": "Nanostack NSDL and COAP library",
"keywords": [
"coap",

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2016 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SN_CONFIG_H
#define SN_CONFIG_H
/**
* \brief Configuration options (set of defines and values)
*
* This lists set of compile-time options that needs to be used to enable
* or disable features selectively, and set the values for the mandatory
* parameters.
*/
/**
* \def SN_COAP_DUPLICATION_MAX_MSGS_COUNT
* \brief For Message duplication detection
* Init value for the maximum count of messages to be stored for duplication detection
* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory
* Default is set to 1.
*/
#undef SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* 1 */
/**
* \def SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
*
* \brief For Message blockwising
* Init value for the maximum payload size to be sent and received at one blockwise message
* Setting of this value to 0 will disable this feature, and also reduce use of ROM memory
* Note: This define is common for both received and sent Blockwise messages
*/
#undef SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* 0 */ // < Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024
/**
* \def COAP_DISABLE_OBS_FEATURE
*
* \brief Disables CoAP 'obs' sending feature
* as part of registration message, this might be
* needed to be enabled for some strict LWM2M server implementation.
* By default, this feature is disabled.
*/
#undef COAP_DISABLE_OBS_FEATURE
/**
* \def SN_COAP_RESENDING_QUEUE_SIZE_MSGS
*
* \brief Sets the number of messages stored
* in the resending queue. Default is 2
*/
#undef SN_COAP_RESENDING_QUEUE_SIZE_MSGS /* 2 */ // < Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature
/**
* \def SN_COAP_RESENDING_QUEUE_SIZE_BYTES
*
* \brief Sets the size of the re-sending buffer.
* Setting this to 0 disables this feature.
* By default, this feature is disabled.
*/
#undef SN_COAP_RESENDING_QUEUE_SIZE_BYTES /* 0 */ // Default re-sending queue size - defines size of the re-sending buffer. Setting this to 0 disables feature
/**
* \def SN_COAP_MAX_INCOMING_MESSAGE_SIZE
*
* \brief Sets the maximum size (in bytes) that
* mbed Client will allow to be handled while
* receiving big payload in blockwise mode.
* Application can set this value based on their
* available storage capability.
* By default, maximum size is UINT16_MAX, 65535 bytes.
*/
#undef SN_COAP_MAX_INCOMING_MESSAGE_SIZE /* UINT16_MAX */
#ifdef MBED_CLIENT_USER_CONFIG_FILE
#include MBED_CLIENT_USER_CONFIG_FILE
#endif
#endif // SN_CONFIG_H

View File

View File

View File

@ -26,6 +26,7 @@
#include "ns_list.h"
#include "sn_coap_header_internal.h"
#include "sn_config.h"
#ifdef __cplusplus
extern "C" {
@ -41,8 +42,27 @@ struct sn_coap_hdr_;
#define ENABLE_RESENDINGS 1 /**< Enable / Disable resending from library in building */
#define SN_COAP_RESENDING_MAX_COUNT 3 /**< Default number of re-sendings */
#ifdef YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_MSGS
#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_MSGS
#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_MSGS
#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_MSGS
#endif
#ifndef SN_COAP_RESENDING_QUEUE_SIZE_MSGS
#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS 2 /**< Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature */
#endif
#ifdef YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_BYTES
#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_BYTES
#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_BYTES
#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_BYTES
#endif
#ifndef SN_COAP_RESENDING_QUEUE_SIZE_BYTES
#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES 0 /**< Default re-sending queue size - defines size of the re-sending buffer. Setting this to 0 disables feature */
#endif
#define DEFAULT_RESPONSE_TIMEOUT 10 /**< Default re-sending timeout as seconds */
/* These parameters sets maximum values application can set with API */
@ -81,7 +101,6 @@ struct sn_coap_hdr_;
/* Init value for the maximum payload size to be sent and received at one blockwise message */
/* Setting of this value to 0 will disable this feature, and also reduce use of ROM memory */
/* Note: Current Coap implementation supports Blockwise transfers specification version draft-ietf-core-block-03 */
/* Note: This define is common for both received and sent Blockwise messages */
#ifdef YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE

View File

View File

@ -29,6 +29,7 @@
#include "sn_coap_protocol_internal.h"
#include "sn_nsdl_lib.h"
#include "sn_grs.h"
#include "sn_config.h"
#include "mbed-trace/mbed_trace.h"
#define TRACE_GROUP "coap"

View File

@ -27,6 +27,7 @@
#include "sn_coap_parser_stub.h"
#include "sn_coap_header_check_stub.h"
int retCounter = 0;
static coap_s *coap_handle = NULL;
void myFree(void* addr);
@ -87,9 +88,13 @@ TEST(libCoap_protocol, sn_coap_protocol_destroy)
msg_ptr->send_msg_ptr->uri_path_len = 2;
ns_list_add_to_end(&handle->linked_list_resent_msgs, msg_ptr);
#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
ns_list_init(&handle->linked_list_duplication_msgs);
#endif
#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
ns_list_init(&handle->linked_list_blockwise_sent_msgs);
ns_list_init(&handle->linked_list_blockwise_received_payloads);
#endif
CHECK( 0 == sn_coap_protocol_destroy(handle));
}

View File

@ -0,0 +1,13 @@
#ifndef TEST_CONFIG_H
#define TEST_CONFIG_H
/**
* \def SN_COAP_DUPLICATION_MAX_MSGS_COUNT
* \brief For Message duplication detection
* Init value for the maximum count of messages to be stored for duplication detection
* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory
* Default is set to 0.
*/
#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT 1
#endif

View File

View File

@ -0,0 +1,32 @@
# Change Log
## [mbed-os.5.2-rc1](https://github.com/ARMmbed/sal-stack-nanostack-eventloop/releases/tag/mbed-os.5.2-rc1) (24-Sep-2016)
[Full Changelog](https://github.com/ARMmbed/sal-stack-nanostack-eventloop/compare/mbed-os-5.0-rc1...mbed-os.5.2-rc1)
**New features**
- Move configuration parameter resolution to separate header and allow user definable configuration header to be used.
- Port eventloop system timer to use new tick timer functions platform_tick_timer_register, platform_tick_timer_start and platform_tick_timer_stop.
**Merged pull requests:**
commit 283299dbd744c91cb30810ad263798842905c054 (HEAD, tag: mbed-os.5.2-rc1, origin/master, origin/HEAD, master)
Author: Jaakko Kukkohovi <jkukkohovi@gmail.com>
Date: Fri Sep 23 10:05:55 2016 +0300
Change configuration method (#23)
Move configuration parameter resolution to separate header and allow
user definable configuration header to be used.
commit 269b00fba6a637c363f7d1690db0889118bca010
Author: Jaakko Kukkohovi <jkukkohovi@gmail.com>
Date: Wed Sep 21 11:27:40 2016 +0300
Systimer using platform tick timer (#22)
* Port eventloop system timer to use new tick timer functions platform_tick_timer_register, platform_tick_timer_start and platform_tick_timer_stop.Existing functionality is preserved by implementing these functions by default using the high resolution timer as before
* New configuration parameter use_platform_tick_timer disables the high resolution timer based tick timer implementation and allows platform to implement the tick timer functions.
* New configuration parameter exclude_highres_timer removes the high resolution timer from the build thus providing only eventloop.
* Minar support now implemented by providing platform tick timer using minar timers and implicitly using platform tick timers for eventloop when using minar

View File

@ -1,322 +0,0 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include "ns_types.h"
#include "ns_list.h"
#include "eventOS_event.h"
#include "eventOS_scheduler.h"
#include "timer_sys.h"
#include "nsdynmemLIB.h"
#include "ns_timer.h"
#include "platform/arm_hal_interrupt.h"
typedef struct arm_core_tasklet_list_s {
int8_t id; /**< Event handler Tasklet ID */
void (*func_ptr)(arm_event_s *);
ns_list_link_t link;
} arm_core_tasklet_list_s;
typedef struct arm_core_event_s {
arm_event_s data;
ns_list_link_t link;
} arm_core_event_s;
static NS_LIST_DEFINE(arm_core_tasklet_list, arm_core_tasklet_list_s, link);
static NS_LIST_DEFINE(event_queue_active, arm_core_event_s, link);
static NS_LIST_DEFINE(free_event_entry, arm_core_event_s, link);
/** Curr_tasklet tell to core and platform which task_let is active, Core Update this automatic when switch Tasklet. */
int8_t curr_tasklet = 0;
static arm_core_tasklet_list_s *tasklet_dynamically_allocate(void);
static arm_core_event_s *event_dynamically_allocate(void);
static arm_core_event_s *event_core_get(void);
static void event_core_write(arm_core_event_s *event);
static arm_core_tasklet_list_s *event_tasklet_handler_get(uint8_t tasklet_id)
{
ns_list_foreach(arm_core_tasklet_list_s, cur, &arm_core_tasklet_list) {
if (cur->id == tasklet_id) {
return cur;
}
}
return NULL;
}
// XXX this can return 0, but 0 seems to mean "none" elsewhere? Or at least
// curr_tasklet is reset to 0 in various places.
static int8_t tasklet_get_free_id(void)
{
/*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/
for (uint8_t i = 0; i <= INT8_MAX; i++) {
if (!event_tasklet_handler_get(i)) {
return i;
}
}
return -1;
}
int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uint8_t init_event_type)
{
arm_core_event_s *event_tmp;
// XXX Do we really want to prevent multiple tasklets with same function?
ns_list_foreach(arm_core_tasklet_list_s, cur, &arm_core_tasklet_list) {
if (cur->func_ptr == handler_func_ptr) {
return -1;
}
}
//Allocate new
arm_core_tasklet_list_s *new = tasklet_dynamically_allocate();
if (!new) {
return -2;
}
event_tmp = event_core_get();
if (!event_tmp) {
ns_dyn_mem_free(new);
return -2;
}
//Fill in tasklet; add to list
new->id = tasklet_get_free_id();
new->func_ptr = handler_func_ptr;
ns_list_add_to_end(&arm_core_tasklet_list, new);
//Queue "init" event for the new task
event_tmp->data.receiver = new->id;
event_tmp->data.sender = 0;
event_tmp->data.event_type = init_event_type;
event_tmp->data.event_data = 0;
event_core_write(event_tmp);
return new->id;
}
/**
* \brief Send event to event scheduler.
*
* \param event pointer to pushed event.
*
* \return 0 Event push OK
* \return -1 Memory allocation Fail
*
*/
int8_t eventOS_event_send(arm_event_s *event)
{
int8_t retval = -1;
if (event_tasklet_handler_get(event->receiver)) {
arm_core_event_s *event_tmp = event_core_get();
if (event_tmp) {
event_tmp->data = *event;
event_core_write(event_tmp);
retval = 0;
}
}
return retval;
}
static arm_core_event_s *event_dynamically_allocate(void)
{
return ns_dyn_mem_alloc(sizeof(arm_core_event_s));
}
static arm_core_tasklet_list_s *tasklet_dynamically_allocate(void)
{
return ns_dyn_mem_alloc(sizeof(arm_core_tasklet_list_s));
}
arm_core_event_s *event_core_get(void)
{
arm_core_event_s *event;
platform_enter_critical();
event = ns_list_get_first(&free_event_entry);
if (event) {
ns_list_remove(&free_event_entry, event);
} else {
event = event_dynamically_allocate();
}
if (event) {
event->data.data_ptr = NULL;
event->data.priority = ARM_LIB_LOW_PRIORITY_EVENT;
}
platform_exit_critical();
return event;
}
static void event_core_free_push(arm_core_event_s *free)
{
platform_enter_critical();
ns_list_add_to_start(&free_event_entry, free);
platform_exit_critical();
}
static arm_core_event_s *event_core_read(void)
{
arm_core_event_s *event;
platform_enter_critical();
event = ns_list_get_first(&event_queue_active);
if (event) {
ns_list_remove(&event_queue_active, event);
}
platform_exit_critical();
return event;
}
void event_core_write(arm_core_event_s *event)
{
platform_enter_critical();
bool added = false;
ns_list_foreach(arm_core_event_s, event_tmp, &event_queue_active) {
// note enum ordering means we're checking if event_tmp is LOWER priority than event
if (event_tmp->data.priority > event->data.priority) {
ns_list_add_before(&event_queue_active, event_tmp, event);
added = true;
break;
}
}
if (!added) {
ns_list_add_to_end(&event_queue_active, event);
}
/* Wake From Idle */
platform_exit_critical();
eventOS_scheduler_signal();
}
/**
*
* \brief Initialize Nanostack Core.
*
* Function Initialize Nanostack Core, Socket Interface,Buffer memory and Send Init event to all Tasklett which are Defined.
*
*/
void eventOS_scheduler_init(void)
{
/* Reset Event List variables */
ns_list_init(&free_event_entry);
ns_list_init(&event_queue_active);
ns_list_init(&arm_core_tasklet_list);
//Allocate 10 entry
for (uint8_t i = 0; i < 10; i++) {
arm_core_event_s *event = event_dynamically_allocate();
if (event) {
ns_list_add_to_start(&free_event_entry, event);
}
}
/* Init Generic timer module */
ns_timer_init();
timer_sys_init(); //initialize timer
/* Set Tasklett switcher to Idle */
curr_tasklet = 0;
}
int8_t eventOS_scheduler_get_active_tasklet(void)
{
return curr_tasklet;
}
void eventOS_scheduler_set_active_tasklet(int8_t tasklet)
{
curr_tasklet = tasklet;
}
int eventOS_scheduler_timer_stop(void)
{
timer_sys_disable();
if (ns_timer_sleep() != 0) {
return 1;
}
return 0;
}
int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks)
{
//Update MS to 10ms ticks
sleep_ticks /= 10;
sleep_ticks++;
system_timer_tick_update(sleep_ticks);
if (timer_sys_wakeup() == 0) {
return 0;
}
return -1;
}
/**
*
* \brief Infinite Event Read Loop.
*
* Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep
*
*/
bool eventOS_scheduler_dispatch_event(void)
{
arm_core_tasklet_list_s *tasklet;
arm_core_event_s *cur_event;
arm_event_s event;
curr_tasklet = 0;
cur_event = event_core_read();
if (cur_event) {
event = cur_event->data;
event_core_free_push(cur_event);
tasklet = event_tasklet_handler_get(event.receiver);
if (tasklet) {
curr_tasklet = event.receiver;
/* Tasklet Scheduler Call */
tasklet->func_ptr(&event);
/* Set Current Tasklet to Idle state */
curr_tasklet = 0;
}
return true;
} else {
return false;
}
}
void eventOS_scheduler_run_until_idle(void)
{
while (eventOS_scheduler_dispatch_event());
}
/**
*
* \brief Infinite Event Read Loop.
*
* Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep
*
*/
NS_NORETURN void eventOS_scheduler_run(void)
{
while (1) {
if (!eventOS_scheduler_dispatch_event()) {
eventOS_scheduler_idle();
}
}
}

View File

@ -1,389 +0,0 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ns_types.h"
#include "ns_list.h"
#include "ns_timer.h"
#include "eventOS_callback_timer.h"
#include "platform/arm_hal_interrupt.h"
#include "platform/arm_hal_timer.h"
#include "nsdynmemLIB.h"
typedef enum ns_timer_state_e {
NS_TIMER_ACTIVE = 0, // Will run on the next HAL interrupt
NS_TIMER_HOLD, // Will run on a later HAL interrupt
NS_TIMER_RUN_INTERRUPT, // Running on the interrupt we're currently handling
NS_TIMER_STOP // Timer not scheduled ("start" not called since last callback)
} ns_timer_state_e;
typedef struct ns_timer_struct {
int8_t ns_timer_id;
ns_timer_state_e timer_state;
uint16_t slots;
uint16_t remaining_slots;
void (*interrupt_handler)(int8_t, uint16_t);
ns_list_link_t link;
} ns_timer_struct;
static NS_LIST_DEFINE(ns_timer_list, ns_timer_struct, link);
#define NS_TIMER_RUNNING 1
static uint8_t ns_timer_state = 0;
#ifdef ATMEGA256RFR2
#define COMPENSATION 3
#define COMPENSATION_TUNE 1
#else
#define COMPENSATION 0
#define COMPENSATION_TUNE 0
#endif
static void ns_timer_interrupt_handler(void);
static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id);
int8_t ns_timer_init(void)
{
/*Set interrupt handler in HAL driver*/
platform_timer_set_cb(ns_timer_interrupt_handler);
return 0;
}
int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t))
{
int8_t retval = -1;
/*Find first free timer ID in timer list*/
/*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/
for (uint8_t i = 0; i <= INT8_MAX; i++) {
if (!ns_timer_get_pointer_to_timer_struct(i)) {
retval = i;
break;
}
}
if (retval == -1) {
return -1;
}
ns_timer_struct *new_timer = ns_dyn_mem_alloc(sizeof(ns_timer_struct));
if (!new_timer) {
return -1;
}
/*Initialise new timer*/
new_timer->ns_timer_id = retval;
new_timer->timer_state = NS_TIMER_STOP;
new_timer->remaining_slots = 0;
new_timer->interrupt_handler = timer_interrupt_handler;
// Critical section sufficient as long as list can't be reordered from
// interrupt, otherwise will need to cover whole routine
platform_enter_critical();
ns_list_add_to_end(&ns_timer_list, new_timer);
platform_exit_critical();
/*Return timer ID*/
return retval;
}
int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id)
{
ns_timer_struct *current_timer;
current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
if (!current_timer) {
return -1;
}
// Critical section sufficient as long as list can't be reordered from
// interrupt, otherwise will need to cover whole routine
platform_enter_critical();
ns_list_remove(&ns_timer_list, current_timer);
platform_exit_critical();
ns_dyn_mem_free(current_timer);
return 0;
}
static int8_t ns_timer_start_pl_timer(uint16_t pl_timer_start_slots)
{
/*Don't start timer with 0 slots*/
if (!pl_timer_start_slots) {
pl_timer_start_slots = 1;
}
/*Start HAL timer*/
platform_timer_start(pl_timer_start_slots);
/*Set HAL timer state to running*/
ns_timer_state |= NS_TIMER_RUNNING;
return 0;
}
int8_t ns_timer_sleep(void)
{
int8_t ret_val = -1;
if (ns_timer_state & NS_TIMER_RUNNING) {
/*Start HAL timer*/
platform_timer_disable();
/*Set HAL timer state to running*/
ns_timer_state &= ~NS_TIMER_RUNNING;
ret_val = 0;
}
return ret_val;
}
static int8_t ns_timer_get_next_running_to(void)
{
uint8_t hold_count = 0;
ns_timer_struct *first_timer = NULL;
/*Find hold-labelled timer with the least remaining slots*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (current_timer->timer_state == NS_TIMER_HOLD) {
if (!first_timer || current_timer->remaining_slots < first_timer->remaining_slots) {
first_timer = current_timer;
}
/*For optimisation, count the found timers*/
hold_count++;
}
}
if (!first_timer) {
return 0;
}
/*If hold-labelled timer found, set it active and start the HAL driver*/
hold_count--;
first_timer->timer_state = NS_TIMER_ACTIVE;
/*Compensate time spent in timer function*/
if (first_timer->remaining_slots > COMPENSATION) {
first_timer->remaining_slots -= COMPENSATION;
}
/*Start HAL timer*/
ns_timer_start_pl_timer(first_timer->remaining_slots);
/*Update other hold-labelled timers*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (hold_count == 0) { // early termination optimisation
break;
}
if (current_timer->timer_state == NS_TIMER_HOLD) {
if (current_timer->remaining_slots == first_timer->remaining_slots) {
current_timer->timer_state = NS_TIMER_ACTIVE;
} else {
current_timer->remaining_slots -= first_timer->remaining_slots;
/*Compensate time spent in timer function*/
if (current_timer->remaining_slots > COMPENSATION) {
current_timer->remaining_slots -= COMPENSATION;
}
}
hold_count--;
}
}
return 0;
}
static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id)
{
/*Find timer with the given ID*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (current_timer->ns_timer_id == timer_id) {
return current_timer;
}
}
return NULL;
}
int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots)
{
int8_t ret_val = 0;
uint16_t pl_timer_remaining_slots;
ns_timer_struct *timer;
platform_enter_critical();
/*Find timer to be activated*/
timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
if (!timer) {
ret_val = -1;
goto exit;
}
// XXX this assumes the timer currently isn't running?
// Is event.c relying on this restarting HAL timer after ns_timer_sleep()?
/*If any timers are active*/
if (ns_timer_state & NS_TIMER_RUNNING) {
/*Get remaining slots of the currently activated timeout*/
pl_timer_remaining_slots = platform_timer_get_remaining_slots();
/*New timeout is shorter than currently enabled timeout*/
if (pl_timer_remaining_slots > slots) {
/*Start HAL timer*/
ns_timer_start_pl_timer(slots - 0);
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
/*Switch active timers to hold*/
if (current_timer->timer_state == NS_TIMER_ACTIVE) {
current_timer->timer_state = NS_TIMER_HOLD;
current_timer->remaining_slots = 0;
}
/*Update hold-labelled timers*/
if (current_timer->timer_state == NS_TIMER_HOLD) {
current_timer->remaining_slots += (pl_timer_remaining_slots - slots);
/*Compensate time spent in timer function*/
if (current_timer->remaining_slots > (COMPENSATION - COMPENSATION_TUNE)) {
current_timer->remaining_slots -= (COMPENSATION - COMPENSATION_TUNE);
}
}
}
/*Mark active and start the timer*/
timer->timer_state = NS_TIMER_ACTIVE;
timer->slots = slots;
timer->remaining_slots = slots;
}
/*New timeout is longer than currently enabled timeout*/
else if (pl_timer_remaining_slots < slots) {
/*Mark hold and update remaining slots*/
timer->timer_state = NS_TIMER_HOLD;
timer->slots = slots;
timer->remaining_slots = (slots - pl_timer_remaining_slots);
}
/*New timeout is equal to currently enabled timeout*/
else {
/*Mark it active and it will be handled in next interrupt*/
timer->timer_state = NS_TIMER_ACTIVE;
timer->slots = slots;
timer->remaining_slots = slots;
}
} else {
/*No timers running*/
timer->timer_state = NS_TIMER_HOLD;
timer->slots = slots;
timer->remaining_slots = slots;
/*Start next timeout*/
ns_timer_get_next_running_to();
}
exit:
platform_exit_critical();
return ret_val;
}
static void ns_timer_interrupt_handler(void)
{
uint8_t i = 0;
platform_enter_critical();
/*Clear timer running state*/
ns_timer_state &= ~NS_TIMER_RUNNING;
/*Mark active timers as NS_TIMER_RUN_INTERRUPT, interrupt functions are called at the end of this function*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (current_timer->timer_state == NS_TIMER_ACTIVE) {
current_timer->timer_state = NS_TIMER_RUN_INTERRUPT;
/*For optimisation, count the found timers*/
i++;
}
}
/*Start next timeout*/
ns_timer_get_next_running_to();
/*Call interrupt functions*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (i == 0) {
break;
}
if (current_timer->timer_state == NS_TIMER_RUN_INTERRUPT) {
current_timer->timer_state = NS_TIMER_STOP;
current_timer->interrupt_handler(current_timer->ns_timer_id, current_timer->slots);
i--;
}
}
platform_exit_critical();
}
int8_t eventOS_callback_timer_stop(int8_t ns_timer_id)
{
uint16_t pl_timer_remaining_slots;
bool active_timer_found = false;
ns_timer_struct *current_timer;
ns_timer_struct *first_timer = NULL;
int8_t retval = -1;
platform_enter_critical();
/*Find timer with given timer ID*/
current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
if (!current_timer) {
goto exit;
}
retval = 0;
/*Check if already stopped*/
if (current_timer->timer_state == NS_TIMER_STOP) {
goto exit;
}
current_timer->timer_state = NS_TIMER_STOP;
current_timer->remaining_slots = 0;
/*Check if some timer is already active*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (current_timer->timer_state == NS_TIMER_ACTIVE) {
active_timer_found = true;
break;
}
}
/*If no active timers found, start one*/
if (!active_timer_found) {
pl_timer_remaining_slots = platform_timer_get_remaining_slots();
/*Find hold-labelled timer with the least remaining slots*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (current_timer->timer_state == NS_TIMER_HOLD) {
current_timer->remaining_slots += pl_timer_remaining_slots;
if (!first_timer || current_timer->remaining_slots < first_timer->remaining_slots) {
first_timer = current_timer;
}
}
}
/*If hold-labelled timer found, set it active and start the HAL driver*/
if (first_timer) {
first_timer->timer_state = NS_TIMER_ACTIVE;
/*Start HAL timer*/
ns_timer_start_pl_timer(first_timer->remaining_slots);
/*If some of the other hold-labelled timers have the same remaining slots as the timer_tmp, mark them active*/
ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
if (current_timer->timer_state == NS_TIMER_HOLD) {
if (current_timer->remaining_slots == first_timer->remaining_slots) {
current_timer->timer_state = NS_TIMER_ACTIVE;
} else {
current_timer->remaining_slots -= first_timer->remaining_slots;
}
}
}
}
}
exit:
platform_exit_critical();
return retval;
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NS_TIMER_H_
#define NS_TIMER_H_
extern int8_t ns_timer_init(void);
extern int8_t ns_timer_sleep(void);
#endif /*NS_TIMER_H_*/

View File

@ -1,109 +0,0 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "eventOS_event.h"
#include "eventOS_event_timer.h"
#include "nsdynmemLIB.h"
#include "ns_list.h"
#define STARTUP_EVENT 0
#define TIMER_EVENT 1
// Timeout structure, already typedefed to timeout_t
struct timeout_entry_t {
void (*callback)(void *);
void *arg;
uint8_t event_id;
ns_list_link_t link;
};
static NS_LIST_HEAD(timeout_t, link) timeout_list = NS_LIST_INIT(timeout_list);
static int8_t timeout_tasklet_id = -1;
static void timeout_tasklet(arm_event_s *event)
{
if (TIMER_EVENT != event->event_type) {
return;
}
timeout_t *found = NULL;
ns_list_foreach_safe(timeout_t, cur, &timeout_list) {
if (cur->event_id == event->event_id) {
found = cur;
ns_list_remove(&timeout_list, cur);
break;
}
}
if (found) {
found->callback(found->arg);
ns_dyn_mem_free(found);
}
}
timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg)
{
uint16_t count;
uint8_t index;
timeout_t *e = ns_dyn_mem_alloc(sizeof(timeout_t));
if (!e) {
return NULL;
}
e->callback = callback;
e->arg = arg;
// Start timeout taskled if it is not running
if (-1 == timeout_tasklet_id) {
timeout_tasklet_id = eventOS_event_handler_create(timeout_tasklet, STARTUP_EVENT);
if (timeout_tasklet_id < 0) {
timeout_tasklet_id = -1;
goto FAIL;
}
}
// Check that we still have indexes left. We have only 8bit timer id.
count = ns_list_count(&timeout_list);
if (count >= UINT8_MAX) { // Too big list, timer_id is uint8_t
goto FAIL;
}
// Find next free index
index = 0;
AGAIN:
ns_list_foreach(timeout_t, cur, &timeout_list) {
if (cur->event_id == index) { // This index was used
index++; // Check next one.
goto AGAIN; // Start checking from begining of the list, indexes are not in order
}
}
e->event_id = index;
ns_list_add_to_end(&timeout_list, e);
eventOS_event_timer_request(index, TIMER_EVENT, timeout_tasklet_id, ms);
return e;
FAIL:
ns_dyn_mem_free(e);
return NULL;
}
void eventOS_timeout_cancel(timeout_t *t)
{
ns_list_foreach_safe(timeout_t, cur, &timeout_list) {
if (t == cur) {
ns_list_remove(&timeout_list, cur);
eventOS_event_timer_cancel(cur->event_id, timeout_tasklet_id);
ns_dyn_mem_free(cur);
}
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _PL_NANO_TIMER_SYS_H_
#define _PL_NANO_TIMER_SYS_H_
/**
* Initialize system timer
* */
extern void timer_sys_init(void);
extern uint32_t timer_get_runtime_ticks(void);
int8_t timer_sys_wakeup(void);
void timer_sys_disable(void);
/**
* System Timer update and synch after sleep
*
* \param ticks Time in 10 ms resolution
*
* \return none
*
* */
void system_timer_tick_update(uint32_t ticks);
#endif /*_PL_NANO_TIMER_SYS_H_*/

View File

@ -0,0 +1,13 @@
{
"name": "nanostack-eventloop",
"config": {
"use_platform_tick_timer": {
"help": "Use platform provided low resolution tick timer for eventloop",
"value": null
},
"exclude_highres_timer": {
"help": "Exclude high resolution timer from build",
"value": null
}
}
}

View File

@ -15,6 +15,9 @@
*/
#ifndef ARM_HAL_TIMER_H_
#define ARM_HAL_TIMER_H_
#include "eventloop_config.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -22,6 +25,7 @@ extern "C" {
* \brief This function perform timer init.
*/
extern void platform_timer_enable(void);
/**
* \brief This function is API for set Timer interrupt handler for stack
*
@ -30,6 +34,7 @@ extern void platform_timer_enable(void);
*/
typedef void (*platform_timer_cb)(void);
extern void platform_timer_set_cb(platform_timer_cb new_fp);
/**
* \brief This function is API for stack timer start
*
@ -37,17 +42,48 @@ extern void platform_timer_set_cb(platform_timer_cb new_fp);
*
*/
extern void platform_timer_start(uint16_t slots);
/**
* \brief This function is API for stack timer stop
*
*/
extern void platform_timer_disable(void);
/**
* \brief This function is API for stack timer to read active timer remaining slot count
*
* \return 50us time slot remaining
*/
extern uint16_t platform_timer_get_remaining_slots(void);
#ifdef NS_EVENTLOOP_USE_TICK_TIMER
/**
* \brief This function is API for registering low resolution tick timer callback. Also does
* any necessary initialization of the tick timer.
*
* \return -1 for failure, success otherwise
*/
extern int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void));
/**
* \brief This function is API for starting the low resolution tick timer. The callback
* set with platform_tick_timer_register gets called periodically until stopped
* by calling platform_tick_timer_stop.
*
* \param period_ms define how many milliseconds time period will be started
* \return -1 for failure, success otherwise
*/
extern int8_t platform_tick_timer_start(uint32_t period_ms);
/**
* \brief This function is API for stopping the low resolution tick timer
*
* \return -1 for failure, success otherwise
*/
extern int8_t platform_tick_timer_stop(void);
#endif // NS_EVENTLOOP_USE_TICK_TIMER
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EVENTLOOP_CONFIG_H_
#define EVENTLOOP_CONFIG_H_
/*
* Undefine all internal flags before evaluating the configuration
*/
#undef NS_EVENTLOOP_USE_TICK_TIMER
#undef NS_EXCLUDE_HIGHRES_TIMER
/*
* mbedOS 5 specific configuration flag mapping to internal flags
*/
#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_USE_PLATFORM_TICK_TIMER
#define NS_EVENTLOOP_USE_TICK_TIMER 1
#endif
#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_EXCLUDE_HIGHRES_TIMER
#define NS_EXCLUDE_HIGHRES_TIMER 1
#endif
/*
* For mbedOS 3 and minar use platform tick timer by default, highres timers should come from eventloop adaptor
*/
#ifdef YOTTA_CFG_MINAR
#define NS_EVENTLOOP_USE_TICK_TIMER 1
#endif
/*
* Include the user config file if defined
*/
#ifdef NS_EVENTLOOP_USER_CONFIG_FILE
#include NS_EVENTLOOP_USER_CONFIG_FILE
#endif
#endif /* EVENTLOOP_CONFIG_H_ */

View File

@ -228,7 +228,6 @@ void eventOS_scheduler_init(void)
}
/* Init Generic timer module */
ns_timer_init();
timer_sys_init(); //initialize timer
/* Set Tasklett switcher to Idle */
curr_tasklet = 0;

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2016 ARM Limited, All Rights Reserved
*/
// Include before mbed.h to properly get UINT*_C()
#include "ns_types.h"
#include "platform/arm_hal_timer.h"
#include "platform/arm_hal_interrupt.h"
#if defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG_MINAR)
#include "minar/minar.h"
#include "mbed-drivers/mbed.h"
#include "core-util/FunctionPointer.h"
#include "core-util/Event.h"
#define TICK_TIMER_ID 1
using minar::Scheduler;
using minar::milliseconds;
using minar::callback_handle_t;
using namespace mbed::util;
static callback_handle_t sys_timer_handle;
static void (*tick_timer_callback)(void);
void timer_callback(void const *funcArgument)
{
(void)funcArgument;
if (NULL != tick_timer_callback) {
tick_timer_callback();
}
}
// Low precision platform tick timer
int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void))
{
tick_timer_callback = tick_timer_cb_handler;
return TICK_TIMER_ID;
}
int8_t platform_tick_timer_start(uint32_t period_ms)
{
int8_t retval = -1;
if (sys_timer_handle != NULL) {
return 0; // Timer already started already so return success
}
Event e = FunctionPointer1<void, void const *>(timer_callback).bind(NULL);
if (e != NULL) {
sys_timer_handle = Scheduler::postCallback(e).period(milliseconds(period_ms)).getHandle();
if (sys_timer_handle != NULL) {
retval = 0;
}
}
return retval;
}
int8_t platform_tick_timer_stop(void)
{
int8_t retval = -1;
if (sys_timer_handle != NULL) {
Scheduler::cancelCallback(sys_timer_handle);
sys_timer_handle = NULL;
retval = 0;
}
return retval;
}
#endif // defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG)

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ns_types.h"
#include "ns_list.h"
#include "ns_timer.h"
@ -21,6 +22,7 @@
#include "platform/arm_hal_timer.h"
#include "nsdynmemLIB.h"
#ifndef NS_EXCLUDE_HIGHRES_TIMER
typedef enum ns_timer_state_e {
NS_TIMER_ACTIVE = 0, // Will run on the next HAL interrupt
NS_TIMER_HOLD, // Will run on a later HAL interrupt
@ -53,18 +55,18 @@ static uint8_t ns_timer_state = 0;
static void ns_timer_interrupt_handler(void);
static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id);
int8_t ns_timer_init(void)
{
/*Set interrupt handler in HAL driver*/
platform_timer_set_cb(ns_timer_interrupt_handler);
return 0;
}
static bool ns_timer_initialized = 0;
int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t))
{
int8_t retval = -1;
if (!ns_timer_initialized) {
/*Set interrupt handler in HAL driver*/
platform_timer_set_cb(ns_timer_interrupt_handler);
ns_timer_initialized = 1;
}
/*Find first free timer ID in timer list*/
/*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/
for (uint8_t i = 0; i <= INT8_MAX; i++) {
@ -374,6 +376,8 @@ int8_t eventOS_callback_timer_stop(int8_t ns_timer_id)
if (current_timer->timer_state == NS_TIMER_HOLD) {
if (current_timer->remaining_slots == first_timer->remaining_slots) {
current_timer->timer_state = NS_TIMER_ACTIVE;
} else {
current_timer->remaining_slots -= first_timer->remaining_slots;
}
}
}
@ -385,3 +389,4 @@ exit:
return retval;
}
#endif // NS_EXCLUDE_HIGHRES_TIMER

View File

@ -20,7 +20,6 @@
extern "C" {
#endif
extern int8_t ns_timer_init(void);
extern int8_t ns_timer_sleep(void);
#ifdef __cplusplus

View File

@ -17,6 +17,7 @@
#include "ns_list.h"
#include "timer_sys.h"
#include "platform/arm_hal_interrupt.h"
#include "platform/arm_hal_timer.h"
#include "ns_timer.h"
#include "nsdynmemLIB.h"
#include "eventOS_event.h"
@ -35,19 +36,53 @@ typedef struct sys_timer_struct_s {
ns_list_link_t link;
} sys_timer_struct_s;
#define TIMER_SLOTS_PER_MS 20
#define TIMER_SYS_TICK_PERIOD 10 // milliseconds
#define TIMER_SYS_TICK_SLOTS (TIMER_SYS_TICK_PERIOD * 20) // 50us slots
static uint32_t run_time_tick_ticks = 0;
static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, link);
static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, link);
static int8_t sys_timer_id = -1;
static sys_timer_struct_s *sys_timer_dynamically_allocate(void);
static void timer_sys_interrupt(int8_t timer_id, uint16_t slots);
static void timer_sys_interrupt(void);
#ifndef NS_EVENTLOOP_USE_TICK_TIMER
static int8_t platform_tick_timer_start(uint32_t period_ms);
/* Implement platform tick timer using eventOS timer */
// platform tick timer callback function
static void (*tick_timer_callback)(void);
static int8_t tick_timer_id = -1; // eventOS timer id for tick timer
// EventOS timer callback function
static void tick_timer_eventOS_callback(int8_t timer_id, uint16_t slots)
{
// Not interested in timer id or slots
(void)slots;
// Call the tick timer callback
if (tick_timer_callback != NULL && timer_id == tick_timer_id) {
platform_tick_timer_start(TIMER_SYS_TICK_PERIOD);
tick_timer_callback();
}
}
static int8_t platform_tick_timer_register(void (*tick_timer_cb)(void))
{
tick_timer_callback = tick_timer_cb;
tick_timer_id = eventOS_callback_timer_register(tick_timer_eventOS_callback);
return tick_timer_id;
}
static int8_t platform_tick_timer_start(uint32_t period_ms)
{
return eventOS_callback_timer_start(tick_timer_id, TIMER_SLOTS_PER_MS * period_ms);
}
static int8_t platform_tick_timer_stop(void)
{
return eventOS_callback_timer_stop(tick_timer_id);
}
#endif // !NS_EVENTLOOP_USE_TICK_TIMER
/*
* Initializes timers and starts system timer
@ -56,8 +91,6 @@ void timer_sys_init(void)
{
run_time_tick_ticks = 0;
sys_timer_id = eventOS_callback_timer_register(timer_sys_interrupt);
// Clear old timers
ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_list) {
ns_list_remove(&system_timer_list, temp);
@ -76,9 +109,8 @@ void timer_sys_init(void)
}
}
if (sys_timer_id >= 0) {
eventOS_callback_timer_start(sys_timer_id, TIMER_SYS_TICK_SLOTS);
}
platform_tick_timer_register(timer_sys_interrupt);
platform_tick_timer_start(TIMER_SYS_TICK_PERIOD);
}
@ -86,7 +118,7 @@ void timer_sys_init(void)
/*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/
void timer_sys_disable(void)
{
eventOS_callback_timer_stop(sys_timer_id);
platform_tick_timer_stop();
}
/*
@ -94,20 +126,12 @@ void timer_sys_disable(void)
*/
int8_t timer_sys_wakeup(void)
{
int8_t ret_val = -1;
if (sys_timer_id >= 0) {
ret_val = eventOS_callback_timer_start(sys_timer_id, TIMER_SYS_TICK_SLOTS);
}
return ret_val;
return platform_tick_timer_start(TIMER_SYS_TICK_PERIOD);
}
static void timer_sys_interrupt(int8_t timer_id, uint16_t slots)
static void timer_sys_interrupt(void)
{
(void)timer_id;
(void)slots;
eventOS_callback_timer_start(sys_timer_id, TIMER_SYS_TICK_SLOTS);
system_timer_tick_update(1);
}
@ -117,7 +141,7 @@ static void timer_sys_interrupt(int8_t timer_id, uint16_t slots)
static sys_timer_struct_s *sys_timer_dynamically_allocate(void)
{
return ns_dyn_mem_alloc(sizeof(sys_timer_struct_s));
return (sys_timer_struct_s*)ns_dyn_mem_alloc(sizeof(sys_timer_struct_s));
}
static sys_timer_struct_s *timer_struct_get(void)

View File

@ -1,234 +0,0 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ns_types.h"
#include "ns_list.h"
#include "timer_sys.h"
#include "platform/arm_hal_interrupt.h"
#include "ns_timer.h"
#include "nsdynmemLIB.h"
#include "eventOS_event.h"
#include "eventOS_event_timer.h"
#include "minar/minar.h"
#include "mbed.h"
#include "core-util/FunctionPointer.h"
#include "core-util/Event.h"
using minar::Scheduler;
using minar::milliseconds;
using minar::callback_handle_t;
using namespace mbed::util;
#ifndef ST_MAX
#define ST_MAX 6
#endif
typedef struct sys_timer_struct_s {
uint32_t timer_sys_launch_time;
int8_t timer_sys_launch_receiver;
uint8_t timer_sys_launch_message;
uint8_t timer_event_type;
ns_list_link_t link;
} sys_timer_struct_s;
#define TIMER_SYS_TICK_PERIOD 10 // milliseconds
static uint32_t run_time_tick_ticks = 0;
static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, link);
static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, link);
static callback_handle_t sys_timer_handle;
static sys_timer_struct_s *sys_timer_dynamically_allocate(void);
/*
* Initializes timers and starts system timer
*/
void timer_sys_init(void)
{
run_time_tick_ticks = 0;
// Clear old timers
ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_list) {
ns_list_remove(&system_timer_list, temp);
ns_dyn_mem_free(temp);
}
// Clear old free timer entrys
ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_free) {
ns_list_remove(&system_timer_free, temp);
ns_dyn_mem_free(temp);
}
for (uint8_t i = 0; i < ST_MAX; i++) {
sys_timer_struct_s *temp = sys_timer_dynamically_allocate();
if (temp) {
ns_list_add_to_start(&system_timer_free, temp);
}
}
Event e = FunctionPointer1<void, uint32_t>(system_timer_tick_update).bind(1);
sys_timer_handle = Scheduler::postCallback(e).period(milliseconds(TIMER_SYS_TICK_PERIOD)).getHandle();
}
/*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/
void timer_sys_disable(void)
{
if (sys_timer_handle != NULL) {
Scheduler::cancelCallback(sys_timer_handle);
sys_timer_handle = NULL;
}
}
/*
* Starts ticking system timer interrupts every 10ms
*/
int8_t timer_sys_wakeup(void)
{
// postCallback should never fail in MINAR
// TODO: check if that's true
if (NULL == sys_timer_handle) {
Event e = FunctionPointer1<void, uint32_t>(system_timer_tick_update).bind(1);
sys_timer_handle = Scheduler::postCallback(e).tolerance(minar::milliseconds(TIMER_SYS_TICK_PERIOD/10)).period(milliseconds(TIMER_SYS_TICK_PERIOD)).getHandle();
}
return 0;
}
/* * * * * * * * * */
static sys_timer_struct_s *sys_timer_dynamically_allocate(void)
{
return (sys_timer_struct_s*)ns_dyn_mem_alloc(sizeof(sys_timer_struct_s));
}
static sys_timer_struct_s *timer_struct_get(void)
{
sys_timer_struct_s *timer;
platform_enter_critical();
timer = ns_list_get_first(&system_timer_free);
if (timer) {
ns_list_remove(&system_timer_free, timer);
} else {
timer = sys_timer_dynamically_allocate();
}
platform_exit_critical();
return timer;
}
uint32_t timer_get_runtime_ticks(void) // only used in dev_stats_internal.c
{
uint32_t ret_val;
platform_enter_critical();
ret_val = run_time_tick_ticks;
platform_exit_critical();
return ret_val;
}
int8_t eventOS_event_timer_request(uint8_t snmessage, uint8_t event_type, int8_t tasklet_id, uint32_t time)
{
int8_t res = -1;
sys_timer_struct_s *timer = NULL;
platform_enter_critical();
// Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks.
// And why shouldn't they be able to get a 1-tick callback?
if (time > 2 * TIMER_SYS_TICK_PERIOD) {
time /= TIMER_SYS_TICK_PERIOD;
// XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe?
time++;
} else {
time = 2;
}
timer = timer_struct_get();
if (timer) {
timer->timer_sys_launch_message = snmessage;
timer->timer_sys_launch_receiver = tasklet_id;
timer->timer_event_type = event_type;
timer->timer_sys_launch_time = time;
ns_list_add_to_start(&system_timer_list, timer);
res = 0;
}
platform_exit_critical();
return res;
}
int8_t eventOS_event_timer_cancel(uint8_t snmessage, int8_t tasklet_id)
{
int8_t res = -1;
platform_enter_critical();
ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) {
if (cur->timer_sys_launch_receiver == tasklet_id && cur->timer_sys_launch_message == snmessage) {
ns_list_remove(&system_timer_list, cur);
ns_list_add_to_start(&system_timer_free, cur);
res = 0;
break;
}
}
platform_exit_critical();
return res;
}
uint32_t eventOS_event_timer_shortest_active_timer(void)
{
uint32_t ret_val = 0;
platform_enter_critical();
ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) {
if (ret_val == 0 || cur->timer_sys_launch_time < ret_val) {
ret_val = cur->timer_sys_launch_time;
}
}
platform_exit_critical();
//Convert ticks to ms
ret_val *= TIMER_SYS_TICK_PERIOD;
return ret_val;
}
void system_timer_tick_update(uint32_t ticks)
{
platform_enter_critical();
//Keep runtime time
run_time_tick_ticks += ticks;
ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) {
if (cur->timer_sys_launch_time <= ticks) {
arm_event_s event;
event.receiver = cur->timer_sys_launch_receiver;
event.sender = 0; /**< Event sender Tasklet ID */
event.data_ptr = NULL;
event.event_type = cur->timer_event_type;
event.event_id = cur->timer_sys_launch_message;
event.event_data = 0;
event.priority = ARM_LIB_MED_PRIORITY_EVENT;
eventOS_event_send(&event);
ns_list_remove(&system_timer_list, cur);
ns_list_add_to_start(&system_timer_free, cur);
} else {
cur->timer_sys_launch_time -= ticks;
}
}
platform_exit_critical();
}