porting: Add FreeRTOS port (based on nRF5 SDK)

This patch adds port of Nimble stack to FreeRTOS based on nRF5 SDK.
It's split into 'common' part which can be used a base for porting to
any other platform and 'freertos_nrf5_sdk' which has FreeRTOS-specific
files and makefile.

Building and flashing is similar to other demo apps from nRF5 SDK:
$ make -C porting/freertos_nrf5_sdk

The resulting image can be flashed on nRF52 DK:
$ make -C porting/freertos_nrf5_sdk flash

Location of nRF5 SDK is set by NRF5_SDK_ROOT variable. By default it is
set to 'nrf5_sdk' subdirectory so a symlink would work just fine:
$ ln -s <x>/nRF5_SDK_12.3.0_d7731ad porting/freertos_nrf5_sdk/nrf5_sdk
This commit is contained in:
Andrzej Kaczmarek
2017-12-20 17:46:30 +01:00
parent b27c0f4bda
commit f1dba08467
73 changed files with 13200 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
# note: no / at the end since it could be either symlink or directory
/porting/freertos_nrf5_sdk/nrf5_sdk
/porting/freertos_nrf5_sdk/_build/
+14
View File
@@ -0,0 +1,14 @@
#ifndef H_BSP_H
#define H_BSP_H
#ifdef __cplusplus
extern "C" {
#endif
#define bssnz_t
#ifdef __cplusplus
}
#endif
#endif /* H_BSP_H */
+116
View File
@@ -0,0 +1,116 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 __CONSOLE_H__
#define __CONSOLE_H__
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
struct os_eventq;
struct console_input {
char line[0];
};
typedef void (*console_rx_cb)(void);
typedef int (*console_append_char_cb)(char *line, uint8_t byte);
typedef void (*completion_cb)(char *str, console_append_char_cb cb);
static int inline
console_is_init(void)
{
return 0;
}
static int inline
console_init(console_rx_cb rx_cb)
{
return 0;
}
static void inline
console_write(const char *str, int cnt)
{
}
static int inline
console_read(char *str, int cnt, int *newline)
{
*newline = 0;
return 0;
}
static void inline
console_blocking_mode(void)
{
}
static void inline
console_non_blocking_mode(void)
{
}
static void inline
console_echo(int on)
{
}
static int inline console_printf(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
static int inline
console_printf(const char *fmt, ...)
{
return 0;
}
static void inline
console_set_queues(struct os_eventq *avail_queue,
struct os_eventq *cmd_queue)
{
}
static void inline
console_set_completion_cb(void (*completion)(char *str, console_append_char_cb cb))
{
}
static int inline
console_handle_char(uint8_t byte)
{
return 0;
}
static int inline
console_out(int character)
{
return 0;
}
#define console_is_midline (0)
#ifdef __cplusplus
}
#endif
#endif /* __CONSOLE__ */
+105
View File
@@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_HAL_TIMER_
#define H_HAL_TIMER_
#include <inttypes.h>
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
#include "os/queue.h"
/* HAL timer struct */
typedef void (*hal_timer_cb)(void *arg);
/**
* The HAL timer structure. The user can declare as many of these structures
* as desired. They are enqueued on a particular HW timer queue when the user
* calls the hal_timer_start or hal_timer_start_at API. The user must have
* called hal_timer_set_cb before starting a timer.
*
* NOTE: the user should not have to modify/examine the contents of this
* structure; the hal timer API should be used.
*/
struct hal_timer
{
void *bsp_timer; /* Internal platform specific pointer */
hal_timer_cb cb_func; /* Callback function */
void *cb_arg; /* Callback argument */
uint32_t expiry; /* Tick at which timer should expire */
TAILQ_ENTRY(hal_timer) link; /* Queue linked list structure */
};
/* Initialize a HW timer. */
int hal_timer_init(int timer_num, void *cfg);
/* Un-initialize a HW timer. */
int hal_timer_deinit(int timer_num);
/*
* Config a HW timer at the given frequency and start it. If the exact
* frequency is not obtainable the closest obtainable frequency is set.
*/
int hal_timer_config(int timer_num, uint32_t freq_hz);
/*
* Returns the resolution of the HW timer. NOTE: the frequency may not be
* obtainable so the caller can use this to determine the resolution.
* Returns resolution in nanoseconds. A return value of 0 indicates an invalid
* timer was used.
*/
uint32_t hal_timer_get_resolution(int timer_num);
/* Returns the HW timer current tick value */
uint32_t hal_timer_read(int timer_num);
/* Perform a blocking delay for a number of ticks. */
int hal_timer_delay(int timer_num, uint32_t ticks);
/*
* Set the timer structure prior to use. Should not be called if the timer
* is running. Must be called at least once prior to using timer.
*/
int hal_timer_set_cb(int timer_num, struct hal_timer *tmr, hal_timer_cb cb_func,
void *arg);
/* Start a timer that will expire in 'ticks' ticks. Ticks cannot be 0 */
int hal_timer_start(struct hal_timer *, uint32_t ticks);
/*
* Start a timer that will expire when the timer reaches 'tick'. If tick
* has already passed the timer callback will be called "immediately" (at
* interrupt context).
*/
int hal_timer_start_at(struct hal_timer *, uint32_t tick);
/* Stop a currently running timer; associated callback will NOT be called */
int hal_timer_stop(struct hal_timer *);
#ifdef __cplusplus
}
#endif
#endif /* H_HAL_TIMER_ */
+64
View File
@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_IGNORE_
#define H_IGNORE_
#ifdef __cplusplus
extern "C" {
#endif
/**
* These macros prevent the "set but not used" warnings for log writes below
* the log level.
*/
#define IGN_1(X) ((void)(X))
#define IGN_2(X, ...) ((void)(X));IGN_1(__VA_ARGS__)
#define IGN_3(X, ...) ((void)(X));IGN_2(__VA_ARGS__)
#define IGN_4(X, ...) ((void)(X));IGN_3(__VA_ARGS__)
#define IGN_5(X, ...) ((void)(X));IGN_4(__VA_ARGS__)
#define IGN_6(X, ...) ((void)(X));IGN_5(__VA_ARGS__)
#define IGN_7(X, ...) ((void)(X));IGN_6(__VA_ARGS__)
#define IGN_8(X, ...) ((void)(X));IGN_7(__VA_ARGS__)
#define IGN_9(X, ...) ((void)(X));IGN_8(__VA_ARGS__)
#define IGN_10(X, ...) ((void)(X));IGN_9(__VA_ARGS__)
#define IGN_11(X, ...) ((void)(X));IGN_10(__VA_ARGS__)
#define IGN_12(X, ...) ((void)(X));IGN_11(__VA_ARGS__)
#define IGN_13(X, ...) ((void)(X));IGN_12(__VA_ARGS__)
#define IGN_14(X, ...) ((void)(X));IGN_13(__VA_ARGS__)
#define IGN_15(X, ...) ((void)(X));IGN_14(__VA_ARGS__)
#define IGN_16(X, ...) ((void)(X));IGN_15(__VA_ARGS__)
#define IGN_17(X, ...) ((void)(X));IGN_16(__VA_ARGS__)
#define IGN_18(X, ...) ((void)(X));IGN_17(__VA_ARGS__)
#define IGN_19(X, ...) ((void)(X));IGN_18(__VA_ARGS__)
#define IGN_20(X, ...) ((void)(X));IGN_19(__VA_ARGS__)
#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
_13, _14, _15, _16, _17, _18, _19, _20, NAME, ...) NAME
#define IGNORE(...) \
GET_MACRO(__VA_ARGS__, IGN_20, IGN_19, IGN_18, IGN_17, IGN_16, IGN_15, \
IGN_14, IGN_13, IGN_12, IGN_11, IGN_10, IGN_9, IGN_8, IGN_7, \
IGN_6, IGN_5, IGN_4, IGN_3, IGN_2, IGN_1)(__VA_ARGS__)
#ifdef __cplusplus
}
#endif
#endif
+89
View File
@@ -0,0 +1,89 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 __SYS_LOG_STUB_H__
#define __SYS_LOG_STUB_H__
#include <inttypes.h>
#include "syscfg/syscfg.h"
#include "log/ignore.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LOG_DEBUG(__l, __mod, ...) IGNORE(__VA_ARGS__)
#define LOG_INFO(__l, __mod, ...) IGNORE(__VA_ARGS__)
#define LOG_WARN(__l, __mod, ...) IGNORE(__VA_ARGS__)
#define LOG_ERROR(__l, __mod, ...) IGNORE(__VA_ARGS__)
#define LOG_CRITICAL(__l, __mod, ...) IGNORE(__VA_ARGS__)
#define LOG_LEVEL_DEBUG 0
#define LOG_LEVEL_INFO 1
#define LOG_LEVEL_WARN 2
#define LOG_LEVEL_ERROR 3
#define LOG_LEVEL_CRITICAL 4
/* Up to 7 custom log levels. */
#define LOG_LEVEL_MAX UINT8_MAX
#define LOG_SYSLEVEL UINT8_MAX
/* Logging medium */
#define LOG_STORE_CONSOLE 1
#define LOG_STORE_CBMEM 2
#define LOG_STORE_FCB 3
/* Global log info */
struct log_info {
uint32_t li_next_index;
uint8_t li_version;
};
struct log_info g_log_info;
struct log {
};
struct log_handler {
};
static inline int
log_register(char *name, struct log *log, const struct log_handler *h,
void *arg, uint8_t level)
{
return 0;
}
static inline void
log_init(void)
{
}
#define log_printf(...)
/*
* Dummy handler exports.
*/
const struct log_handler log_console_handler;
const struct log_handler log_cbmem_handler;
const struct log_handler log_fcb_handler;
#ifdef __cplusplus
}
#endif
#endif /* __SYS_LOG_STUB_H__ */
+66
View File
@@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_UTIL_MEM_
#define H_UTIL_MEM_
#ifdef __cplusplus
extern "C" {
#endif
struct os_mempool;
struct os_mbuf_pool;
int mem_malloc_mempool(struct os_mempool *mempool, int num_blocks,
int block_size, char *name, void **out_buf);
int mem_malloc_mbuf_pool(struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, char *name,
void **out_buf);
int mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, char *name,
void **out_buf);
int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, char *name);
/**
* Specifies a function used as a callback. Functions of this type allocate an
* mbuf chain meant to hold a packet fragment. The resulting mbuf must contain
* a pkthdr.
*
* @param frag_size The number of data bytes that the mbuf will
* eventually contain.
* @param arg A generic parameter.
*
* @return An allocated mbuf chain on success;
* NULL on failure.
*/
typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
struct os_mbuf *mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
mem_frag_alloc_fn *alloc_cb, void *cb_arg);
#ifdef __cplusplus
}
#endif
#endif
+35
View File
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 __NIMBLE_PORT_H__
#define __NIMBLE_PORT_H__
#ifdef __cplusplus
extern "C" {
#endif
void nimble_init(void);
void nimble_run(void);
#ifdef __cplusplus
}
#endif
#endif /* __NIMBLE_PORT_H__ */
+225
View File
@@ -0,0 +1,225 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_ENDIAN_
#define H_ENDIAN_
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Internal helpers */
#ifndef os_bswap_64
#define os_bswap_64(x) ((uint64_t) \
((((x) & 0xff00000000000000ull) >> 56) | \
(((x) & 0x00ff000000000000ull) >> 40) | \
(((x) & 0x0000ff0000000000ull) >> 24) | \
(((x) & 0x000000ff00000000ull) >> 8) | \
(((x) & 0x00000000ff000000ull) << 8) | \
(((x) & 0x0000000000ff0000ull) << 24) | \
(((x) & 0x000000000000ff00ull) << 40) | \
(((x) & 0x00000000000000ffull) << 56)))
#endif
#ifndef os_bswap_32
#define os_bswap_32(x) ((uint32_t) \
((((x) & 0xff000000) >> 24) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x000000ff) << 24)))
#endif
#ifndef os_bswap_16
#define os_bswap_16(x) ((uint16_t) \
((((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8)))
#endif
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#ifndef ntohll
#define ntohll(x) ((uint64_t)(x))
#endif
#ifndef htonll
#define htonll(x) ((uint64_t)(x))
#endif
#ifndef ntohl
#define ntohl(x) ((uint32_t)(x))
#endif
#ifndef htonl
#define htonl(x) ((uint32_t)(x))
#endif
#ifndef ntohs
#define ntohs(x) ((uint16_t)(x))
#endif
#ifndef htons
#define htons(x) ((uint16_t)(x))
#endif
#ifndef htobe16
#define htobe16(x) ((uint16_t)(x))
#endif
#ifndef htole16
#define htole16(x) os_bswap_16 (x)
#endif
#ifndef be16toh
#define be16toh(x) ((uint16_t)(x))
#endif
#ifndef le16toh
#define le16toh(x) os_bswap_16 (x)
#endif
#ifndef htobe32
#define htobe32(x) ((uint32_t)(x))
#endif
#ifndef htole32
#define htole32(x) os_bswap_32 (x)
#endif
#ifndef be32toh
#define be32toh(x) ((uint32_t)(x))
#endif
#ifndef le32toh
#define le32toh(x) os_bswap_32 (x)
#endif
#ifndef htobe64
#define htobe64(x) ((uint64_t)(x))
#endif
#ifndef htole64
#define htole64(x) os_bswap_64 (x)
#endif
#ifndef be64toh
#define be64toh(x) ((uint64_t)(x))
#endif
#ifndef le64toh
#define le64toh(x) os_bswap_64 (x)
#endif
#else
#ifndef ntohll
#define ntohll(x) os_bswap_64(x)
#endif
#ifndef htonll
#define htonll ntohll
#endif
#ifndef ntohl
#define ntohl(x) os_bswap_32(x)
#endif
#ifndef htonl
#define htonl ntohl
#endif
#ifndef htons
#define htons(x) os_bswap_16(x)
#endif
#ifndef ntohs
#define ntohs htons
#endif
#ifndef htobe16
#define htobe16(x) os_bswap_16(x)
#endif
#ifndef htole16
#define htole16(x) ((uint16_t)(x))
#endif
#ifndef be16toh
#define be16toh(x) os_bswap_16(x)
#endif
#ifndef le16toh
#define le16toh(x) ((uint16_t)(x))
#endif
#ifndef htobe32
#define htobe32(x) os_bswap_32(x)
#endif
#ifndef htole32
#define htole32(x) ((uint32_t)(x))
#endif
#ifndef be32toh
#define be32toh(x) os_bswap_32(x)
#endif
#ifndef le32toh
#define le32toh(x) ((uint32_t)(x))
#endif
#ifndef htobe64
#define htobe64(x) os_bswap64(x)
#endif
#ifndef htole64
#define htole64(x) ((uint64_t)(x))
#endif
#ifndef be64toh
#define be64toh(x) os_bswap64(x)
#endif
#ifndef le64toh
#define le64toh(x) ((uint64_t)(x))
#endif
#endif
void put_le16(void *buf, uint16_t x);
void put_le32(void *buf, uint32_t x);
void put_le64(void *buf, uint64_t x);
uint16_t get_le16(const void *buf);
uint32_t get_le32(const void *buf);
uint64_t get_le64(const void *buf);
void put_be16(void *buf, uint16_t x);
void put_be32(void *buf, uint32_t x);
void put_be64(void *buf, uint64_t x);
uint16_t get_be16(const void *buf);
uint32_t get_be32(const void *buf);
uint64_t get_be64(const void *buf);
void swap_in_place(void *buf, int len);
void swap_buf(uint8_t *dst, const uint8_t *src, int len);
#ifdef __cplusplus
}
#endif
#endif
+99
View File
@@ -0,0 +1,99 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_H
#define _OS_H
#include <stdlib.h>
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef min
#define min(a, b) ((a)<(b)?(a):(b))
#endif
#ifndef max
#define max(a, b) ((a)>(b)?(a):(b))
#endif
#define os_get_return_addr() (__builtin_return_address(0))
#define OS_ALIGN(__n, __a) ( \
(((__n) & ((__a) - 1)) == 0) ? \
(__n) : \
((__n) + ((__a) - ((__n) & ((__a) - 1)))) \
)
#define CTASSERT(x) typedef int __ctasssert ## __LINE__[(x) ? 1 : -1]
/**
* Whether or not the operating system has been started. Set to
* 1 right before first task is run.
*/
extern int g_os_started;
int os_info_init(void);
/**
* Returns 1 if the OS has been started, 0 if it has not yet been
* been started.
*/
int os_started(void);
#define OS_WAIT_FOREVER (-1)
#define OS_IDLE_PRIO (0xff)
#define OS_MAIN_TASK_PRIO MYNEWT_VAL(OS_MAIN_TASK_PRIO)
#define OS_MAIN_STACK_SIZE MYNEWT_VAL(OS_MAIN_STACK_SIZE)
void os_init(int (*fn)(int argc, char **argv));
void os_start(void);
/* XXX: Not sure if this should go here; I want to differentiate API that
* should be called by application developers as those that should not. */
void os_init_idle_task(void);
#include "os/endian.h"
#include "os/os_arch.h"
#include "os/os_callout.h"
#include "os/os_cputime.h"
#include "os/os_dev.h"
#include "os/os_error.h"
#include "os/os_eventq.h"
#include "os/os_heap.h"
#include "os/os_fault.h"
#include "os/os_mbuf.h"
#include "os/os_mempool.h"
#include "os/os_mutex.h"
#include "os/os_sanity.h"
#include "os/os_sched.h"
#include "os/os_sem.h"
#include "os/os_task.h"
#include "os/os_time.h"
#ifdef __cplusplus
}
#endif
#endif /* _OS_H */
+26
View File
@@ -0,0 +1,26 @@
#ifndef _OS_ARCH_H
#define _OS_ARCH_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int os_sr_t;
typedef int os_stack_t;
#define OS_ALIGNMENT (4)
#define OS_TICKS_PER_SEC (1000)
extern void vPortEnterCritical(void);
extern void vPortExitCritical(void);
#define OS_ENTER_CRITICAL(unused) do { (void)unused; vPortEnterCritical(); } while (0)
#define OS_EXIT_CRITICAL(unused) do { (void)unused; vPortExitCritical(); } while (0)
#ifdef __cplusplus
}
#endif
#endif /* _OS_ARCH_H */
+62
View File
@@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_CALLOUT_H
#define _OS_CALLOUT_H
#ifdef __cplusplus
extern "C" {
#endif
#define OS_CALLOUT_F_QUEUED (0x01)
#include "os/os_eventq.h"
struct os_callout {
struct os_event c_ev;
struct os_eventq *c_evq;
uint32_t c_ticks;
TAILQ_ENTRY(os_callout) c_next;
};
TAILQ_HEAD(os_callout_list, os_callout);
void os_callout_init(struct os_callout *cf, struct os_eventq *evq,
os_event_fn *ev_cb, void *ev_arg);
void os_callout_stop(struct os_callout *);
int os_callout_reset(struct os_callout *, int32_t);
void os_callout_tick(void);
os_time_t os_callout_wakeup_ticks(os_time_t now);
os_time_t os_callout_remaining_ticks(struct os_callout *c, os_time_t now);
static inline int
os_callout_queued(struct os_callout *c)
{
return c->c_next.tqe_prev != NULL;
}
#ifdef __cplusplus
}
#endif
#endif /* _OS_CALLOUT_H */
+33
View File
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_CFG_H_
#define _OS_CFG_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* _OS_CFG_H_ */
+242
View File
@@ -0,0 +1,242 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_OS_CPUTIME_
#define H_OS_CPUTIME_
#ifdef __cplusplus
extern "C" {
#endif
#include "syscfg/syscfg.h"
#include "os/queue.h"
#include "hal/hal_timer.h"
/*
* NOTE: these definitions allow one to override the cputime frequency used.
* The reason these definitions exist is to make the code more
* efficient/smaller when CPUTIME counts at 1 MHz.
*
* For those who want a different cputime frequency, you can set the config
* definition for OS_CPUTIME_FREQ to the desired frequency in your project,
* target or bsp.
*/
#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 1000000)
#define OS_CPUTIME_FREQ_1MHZ
#elif MYNEWT_VAL(OS_CPUTIME_FREQ) == 256 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 512 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 1024 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 2048 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 4096 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 8192 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 16384 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 65536 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 131072 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 262144 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 524288
#define OS_CPUTIME_FREQ_PWR2
#elif MYNEWT_VAL(OS_CPUTIME_FREQ) > 1000000
#define OS_CPUTIME_FREQ_HIGH
#else
#error "Invalid OS_CPUTIME_FREQ value. Value must be one of a) a power of 2" \
">= 256Hz, or b) any value >= 1MHz"
#endif
#if defined(OS_CPUTIME_FREQ_HIGH)
/* CPUTIME data. */
struct os_cputime_data
{
uint32_t ticks_per_usec; /* number of ticks per usec */
};
extern struct os_cputime_data g_os_cputime;
#endif
/* Helpful macros to compare cputimes */
#define CPUTIME_LT(__t1, __t2) ((int32_t) ((__t1) - (__t2)) < 0)
#define CPUTIME_GT(__t1, __t2) ((int32_t) ((__t1) - (__t2)) > 0)
#define CPUTIME_GEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) >= 0)
#define CPUTIME_LEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) <= 0)
/**
* os cputime init
*
* Initialize the cputime module. This must be called after os_init is called
* and before any other timer API are used. This should be called only once
* and should be called before the hardware timer is used.
*
* @param clock_freq The desired cputime frequency, in hertz (Hz).
*
* @return int 0 on success; -1 on error.
*/
int os_cputime_init(uint32_t clock_freq);
/**
* os cputime get32
*
* Returns the low 32 bits of cputime.
*
* @return uint32_t The lower 32 bits of cputime
*/
uint32_t os_cputime_get32(void);
#if !defined(OS_CPUTIME_FREQ_PWR2)
/**
* os cputime nsecs to ticks
*
* Converts the given number of nanoseconds into cputime ticks.
*
* @param usecs The number of nanoseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'nsecs'
*/
uint32_t os_cputime_nsecs_to_ticks(uint32_t nsecs);
/**
* os cputime ticks to nsecs
*
* Convert the given number of ticks into nanoseconds.
*
* @param ticks The number of ticks to convert to nanoseconds.
*
* @return uint32_t The number of nanoseconds corresponding to 'ticks'
*/
uint32_t os_cputime_ticks_to_nsecs(uint32_t ticks);
/**
* os cputime delay nsecs
*
* Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
*
* @param nsecs The number of nanoseconds to wait.
*/
void os_cputime_delay_nsecs(uint32_t nsecs);
#endif
#if defined(OS_CPUTIME_FREQ_1MHZ)
#define os_cputime_usecs_to_ticks(x) (x)
#define os_cputime_ticks_to_usecs(x) (x)
#else
/**
* os cputime usecs to ticks
*
* Converts the given number of microseconds into cputime ticks.
*
* @param usecs The number of microseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'usecs'
*/
uint32_t os_cputime_usecs_to_ticks(uint32_t usecs);
/**
* os cputime ticks to usecs
*
* Convert the given number of ticks into microseconds.
*
* @param ticks The number of ticks to convert to microseconds.
*
* @return uint32_t The number of microseconds corresponding to 'ticks'
*/
uint32_t os_cputime_ticks_to_usecs(uint32_t ticks);
#endif
/**
* os cputime delay ticks
*
* Wait until the number of ticks has elapsed. This is a blocking delay.
*
* @param ticks The number of ticks to wait.
*/
void os_cputime_delay_ticks(uint32_t ticks);
/**
* os cputime delay usecs
*
* Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
*
* @param usecs The number of usecs to wait.
*/
void os_cputime_delay_usecs(uint32_t usecs);
/**
* os cputime timer init
*
* @param timer The timer to initialize. Cannot be NULL.
* @param fp The timer callback function. Cannot be NULL.
* @param arg Pointer to data object to pass to timer.
*/
void os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp, void *arg);
/**
* os cputime timer start
*
* Start a cputimer that will expire at 'cputime'. If cputime has already
* passed, the timer callback will still be called (at interrupt context).
*
* NOTE: This must be called when the timer is stopped.
*
* @param timer Pointer to timer to start. Cannot be NULL.
* @param cputime The cputime at which the timer should expire.
*
* @return int 0 on success; EINVAL if timer already started or timer struct
* invalid
*
*/
int os_cputime_timer_start(struct hal_timer *timer, uint32_t cputime);
/**
* os cputimer timer relative
*
* Sets a cpu timer that will expire 'usecs' microseconds from the current
* cputime.
*
* NOTE: This must be called when the timer is stopped.
*
* @param timer Pointer to timer. Cannot be NULL.
* @param usecs The number of usecs from now at which the timer will expire.
*
* @return int 0 on success; EINVAL if timer already started or timer struct
* invalid
*/
int os_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs);
/**
* os cputime timer stop
*
* Stops a cputimer from running. The timer is removed from the timer queue
* and interrupts are disabled if no timers are left on the queue. Can be
* called even if timer is not running.
*
* @param timer Pointer to cputimer to stop. Cannot be NULL.
*/
void os_cputime_timer_stop(struct hal_timer *timer);
#ifdef __cplusplus
}
#endif
#endif /* H_OS_CPUTIME_ */
+123
View File
@@ -0,0 +1,123 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_DEV_H
#define _OS_DEV_H
#include <os/os.h>
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_dev;
/*
* Initialization order, defines when a device should be initialized
* by the Mynewt kernel.
*
*/
#define OS_DEV_INIT_PRIMARY (1)
#define OS_DEV_INIT_SECONDARY (2)
#define OS_DEV_INIT_KERNEL (3)
#define OS_DEV_INIT_F_CRITICAL (1 << 0)
#define OS_DEV_INIT_PRIO_DEFAULT (0xff)
/**
* Device status, so functions can ensure device is called in a
* consistent state.
*/
#define OS_DEV_F_STATUS_READY (1 << 0)
#define OS_DEV_F_STATUS_OPEN (1 << 1)
#define OS_DEV_F_STATUS_SUSPENDED (1 << 2)
#define OS_DEV_F_INIT_CRITICAL (1 << 3)
typedef int (*os_dev_init_func_t)(struct os_dev *, void *);
typedef int (*os_dev_open_func_t)(struct os_dev *, uint32_t,
void *);
typedef int (*os_dev_suspend_func_t)(struct os_dev *, os_time_t, int);
typedef int (*os_dev_resume_func_t)(struct os_dev *);
typedef int (*os_dev_close_func_t)(struct os_dev *);
struct os_dev_handlers {
os_dev_open_func_t od_open;
os_dev_suspend_func_t od_suspend;
os_dev_resume_func_t od_resume;
os_dev_close_func_t od_close;
};
/*
* Device structure.
*/
struct os_dev {
struct os_dev_handlers od_handlers;
os_dev_init_func_t od_init;
void *od_init_arg;
uint8_t od_stage;
uint8_t od_priority;
uint8_t od_open_ref;
uint8_t od_flags;
char *od_name;
STAILQ_ENTRY(os_dev) od_next;
};
#define OS_DEV_SETHANDLERS(__dev, __open, __close) \
(__dev)->od_handlers.od_open = (__open); \
(__dev)->od_handlers.od_close = (__close);
static inline int
os_dev_suspend(struct os_dev *dev, os_time_t suspend_t, uint8_t force)
{
if (dev->od_handlers.od_suspend == NULL) {
return (0);
} else {
return (dev->od_handlers.od_suspend(dev, suspend_t, force));
}
}
static inline int
os_dev_resume(struct os_dev *dev)
{
if (dev->od_handlers.od_resume == NULL) {
return (0);
} else {
return (dev->od_handlers.od_resume(dev));
}
}
int os_dev_create(struct os_dev *dev, char *name, uint8_t stage,
uint8_t priority, os_dev_init_func_t od_init, void *arg);
struct os_dev *os_dev_lookup(char *name);
int os_dev_initialize_all(uint8_t stage);
int os_dev_suspend_all(os_time_t, uint8_t);
int os_dev_resume_all(void);
struct os_dev *os_dev_open(char *devname, uint32_t timo, void *arg);
int os_dev_close(struct os_dev *dev);
void os_dev_reset(void);
#ifdef __cplusplus
}
#endif
#endif /* _OS_DEV_H */
+52
View File
@@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_OS_ERROR_
#define H_OS_ERROR_
#include "syscfg/syscfg.h"
#ifdef __cplusplus
extern "C" {
#endif
/* OS error enumerations */
enum os_error {
OS_OK = 0,
OS_ENOMEM = 1,
OS_EINVAL = 2,
OS_INVALID_PARM = 3,
OS_MEM_NOT_ALIGNED = 4,
OS_BAD_MUTEX = 5,
OS_TIMEOUT = 6,
OS_ERR_IN_ISR = 7, /* Function cannot be called from ISR */
OS_ERR_PRIV = 8, /* Privileged access error */
OS_NOT_STARTED = 9, /* OS must be started to call this function, but isn't */
OS_ENOENT = 10, /* No such thing */
OS_EBUSY = 11, /* Resource busy */
OS_ERROR = 12, /* Generic Error */
};
typedef enum os_error os_error_t;
#ifdef __cplusplus
}
#endif
#endif
+68
View File
@@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_EVENTQ_H
#define _OS_EVENTQ_H
#include <inttypes.h>
#include "os/os_time.h"
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_event;
typedef void os_event_fn(struct os_event *ev);
struct os_event {
uint8_t ev_queued;
os_event_fn *ev_cb;
void *ev_arg;
STAILQ_ENTRY(os_event) ev_next;
};
#define OS_EVENT_QUEUED(__ev) ((__ev)->ev_queued)
struct os_eventq {
struct os_task *evq_owner; /* owner task */
struct os_task *evq_task; /* sleeper; must be either NULL, or the owner */
STAILQ_HEAD(, os_event) evq_list;
};
void os_eventq_init(struct os_eventq *);
int os_eventq_inited(const struct os_eventq *evq);
void os_eventq_put(struct os_eventq *, struct os_event *);
struct os_event *os_eventq_get_no_wait(struct os_eventq *evq);
struct os_event *os_eventq_get(struct os_eventq *);
void os_eventq_run(struct os_eventq *evq);
struct os_event *os_eventq_poll(struct os_eventq **, int, os_time_t);
void os_eventq_remove(struct os_eventq *, struct os_event *);
struct os_eventq *os_eventq_dflt_get(void);
/* [DEPRECATED] */
void os_eventq_designate(struct os_eventq **dst, struct os_eventq *val,
struct os_event *start_ev);
#ifdef __cplusplus
}
#endif
#endif /* _OS_EVENTQ_H */
+34
View File
@@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_FAULT_H
#define _OS_FAULT_H
#ifdef __cplusplus
extern "c" {
#endif
void __assert_func(const char *, int, const char *, const char *)
__attribute((noreturn));
#ifdef __cplusplus
}
#endif
#endif /* _OS_FAULT_H */
+38
View File
@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_OS_HEAP_
#define H_OS_HEAP_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *os_malloc(size_t size);
void os_free(void *mem);
void *os_realloc(void *ptr, size_t size);
#ifdef __cplusplus
}
#endif
#endif
+42
View File
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_OS_MALLOC_
#define H_OS_MALLOC_
#include "os/os_heap.h"
#ifdef __cplusplus
extern "C" {
#endif
#undef malloc
#define malloc os_malloc
#undef free
#define free os_free
#undef realloc
#define realloc os_realloc
#ifdef __cplusplus
}
#endif
#endif
+305
View File
@@ -0,0 +1,305 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_MBUF_H
#define _OS_MBUF_H
#include "os/queue.h"
#include "os/os_eventq.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* A mbuf pool from which to allocate mbufs. This contains a pointer to the os
* mempool to allocate mbufs out of, the total number of elements in the pool,
* and the amount of "user" data in a non-packet header mbuf. The total pool
* size, in bytes, should be:
* os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
*/
struct os_mbuf_pool {
/**
* Total length of the databuf in each mbuf. This is the size of the
* mempool block, minus the mbuf header
*/
uint16_t omp_databuf_len;
/**
* Total number of memblock's allocated in this mempool.
*/
uint16_t omp_mbuf_count;
/**
* The memory pool which to allocate mbufs out of
*/
struct os_mempool *omp_pool;
/**
* Link to the next mbuf pool for system memory pools.
*/
STAILQ_ENTRY(os_mbuf_pool) omp_next;
};
/**
* A packet header structure that preceeds the mbuf packet headers.
*/
struct os_mbuf_pkthdr {
/**
* Overall length of the packet.
*/
uint16_t omp_len;
/**
* Flags
*/
uint16_t omp_flags;
/**
* Next packet in the mbuf chain.
*/
STAILQ_ENTRY(os_mbuf_pkthdr) omp_next;
};
/**
* Chained memory buffer.
*/
struct os_mbuf {
/**
* Current pointer to data in the structure
*/
uint8_t *om_data;
/**
* Flags associated with this buffer, see OS_MBUF_F_* defintions
*/
uint8_t om_flags;
/**
* Length of packet header
*/
uint8_t om_pkthdr_len;
/**
* Length of data in this buffer
*/
uint16_t om_len;
/**
* The mbuf pool this mbuf was allocated out of
*/
struct os_mbuf_pool *om_omp;
/**
* Pointer to next entry in the chained memory buffer
*/
SLIST_ENTRY(os_mbuf) om_next;
/**
* Pointer to the beginning of the data, after this buffer
*/
uint8_t om_databuf[0];
};
struct os_mqueue {
STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
struct os_event mq_ev;
};
/*
* Given a flag number, provide the mask for it
*
* @param __n The number of the flag in the mask
*/
#define OS_MBUF_F_MASK(__n) (1 << (__n))
/*
* Checks whether a given mbuf is a packet header mbuf
*
* @param __om The mbuf to check
*/
#define OS_MBUF_IS_PKTHDR(__om) \
((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr))
/* Get a packet header pointer given an mbuf pointer */
#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *) \
((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
/* Given a mbuf packet header pointer, return a pointer to the mbuf */
#define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \
(struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
/**
* Gets the length of an entire mbuf chain. The specified mbuf must have a
* packet header.
*/
#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
/*
* Access the data of a mbuf, and cast it to type
*
* @param __om The mbuf to access, and cast
* @param __type The type to cast it to
*/
#define OS_MBUF_DATA(__om, __type) \
(__type) ((__om)->om_data)
/**
* Access the "user header" in the head of an mbuf chain.
*
* @param om Pointer to the head of an mbuf chain.
*/
#define OS_MBUF_USRHDR(om) \
(void *)((uint8_t *)om + sizeof (struct os_mbuf) + \
sizeof (struct os_mbuf_pkthdr))
/**
* Retrieves the length of the user header in an mbuf.
*
* @param om Pointer to the mbuf to query.
*/
#define OS_MBUF_USRHDR_LEN(om) \
((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr))
/*
* Called by OS_MBUF_LEADINGSPACE() macro
*/
static inline uint16_t
_os_mbuf_leadingspace(struct os_mbuf *om)
{
uint16_t startoff;
uint16_t leadingspace;
startoff = 0;
if (OS_MBUF_IS_PKTHDR(om)) {
startoff = om->om_pkthdr_len;
}
leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
((uint8_t *) &om->om_databuf[0] + startoff));
return (leadingspace);
}
/**
* Returns the leading space (space at the beginning) of the mbuf.
* Works on both packet header, and regular mbufs, as it accounts
* for the additional space allocated to the packet header.
*
* @param __omp Is the mbuf pool (which contains packet header length.)
* @param __om Is the mbuf in that pool to get the leadingspace for
*
* @return Amount of leading space available in the mbuf
*/
#define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om)
/* Called by OS_MBUF_TRAILINGSPACE() macro. */
static inline uint16_t
_os_mbuf_trailingspace(struct os_mbuf *om)
{
struct os_mbuf_pool *omp;
omp = om->om_omp;
return (&om->om_databuf[0] + omp->omp_databuf_len) -
(om->om_data + om->om_len);
}
/**
* Returns the trailing space (space at the end) of the mbuf.
* Works on both packet header and regular mbufs.
*
* @param __omp The mbuf pool for this mbuf
* @param __om Is the mbuf in that pool to get trailing space for
*
* @return The amount of trailing space available in the mbuf
*/
#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
/* Mbuf queue functions */
/* Initialize a mbuf queue */
int os_mqueue_init(struct os_mqueue *mq, os_event_fn *ev_cb, void *arg);
/* Get an element from a mbuf queue */
struct os_mbuf *os_mqueue_get(struct os_mqueue *);
/* Put an element in a mbuf queue */
int os_mqueue_put(struct os_mqueue *, struct os_eventq *, struct os_mbuf *);
/* Register an mbuf pool with the system pool registry */
int os_msys_register(struct os_mbuf_pool *);
/* Return a mbuf from the system pool, given an indicative mbuf size */
struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
/* De-registers all mbuf pools from msys. */
void os_msys_reset(void);
/* Return a packet header mbuf from the system pool */
struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
int os_msys_count(void);
int os_msys_num_free(void);
/* Initialize a mbuf pool */
int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
uint16_t, uint16_t);
/* Allocate a new mbuf out of the os_mbuf_pool */
struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
/* Allocate a new packet header mbuf out of the os_mbuf_pool */
struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
uint8_t pkthdr_len);
/* Duplicate a mbuf from the pool */
struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
uint16_t *out_off);
/* Copy data from an mbuf to a flat buffer. */
int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
/* Append data onto a mbuf */
int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
uint16_t src_off, uint16_t len);
/* Free a mbuf */
int os_mbuf_free(struct os_mbuf *mb);
/* Free a mbuf chain */
int os_mbuf_free_chain(struct os_mbuf *om);
void os_mbuf_adj(struct os_mbuf *mp, int req_len);
int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
const struct os_mbuf *om2, uint16_t offset2,
uint16_t len);
struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
#ifdef __cplusplus
}
#endif
#endif /* _OS_MBUF_H */
+108
View File
@@ -0,0 +1,108 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_MEMPOOL_H_
#define _OS_MEMPOOL_H_
#include <stdbool.h>
#include "os/os.h"
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* A memory block structure. This simply contains a pointer to the free list
* chain and is only used when the block is on the free list. When the block
* has been removed from the free list the entire memory block is usable by the
* caller.
*/
struct os_memblock {
SLIST_ENTRY(os_memblock) mb_next;
};
/* XXX: Change this structure so that we keep the first address in the pool? */
/* XXX: add memory debug structure and associated code */
/* XXX: Change how I coded the SLIST_HEAD here. It should be named:
SLIST_HEAD(,os_memblock) mp_head; */
/* Memory pool */
struct os_mempool {
int mp_block_size; /* Size of the memory blocks, in bytes. */
int mp_num_blocks; /* The number of memory blocks. */
int mp_num_free; /* The number of free blocks left */
int mp_min_free; /* The lowest number of free blocks seen */
uint32_t mp_membuf_addr; /* Address of memory buffer used by pool */
STAILQ_ENTRY(os_mempool) mp_list;
SLIST_HEAD(,os_memblock); /* Pointer to list of free blocks */
char *name; /* Name for memory block */
};
#define OS_MEMPOOL_INFO_NAME_LEN (32)
struct os_mempool_info {
int omi_block_size;
int omi_num_blocks;
int omi_num_free;
int omi_min_free;
char omi_name[OS_MEMPOOL_INFO_NAME_LEN];
};
struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
struct os_mempool_info *);
/*
* To calculate size of the memory buffer needed for the pool. NOTE: This size
* is NOT in bytes! The size is the number of os_membuf_t elements required for
* the memory pool.
*/
#if (OS_CFG_ALIGNMENT == OS_CFG_ALIGN_4)
#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 3) / 4) * (n))
typedef uint32_t os_membuf_t;
#else
#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 7) / 8) * (n))
typedef uint64_t os_membuf_t;
#endif
/** Calculates the number of bytes required to initialize a memory pool. */
#define OS_MEMPOOL_BYTES(n,blksize) \
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
/* Initialize a memory pool */
os_error_t os_mempool_init(struct os_mempool *mp, int blocks, int block_size,
void *membuf, char *name);
/* Performs an integrity check of the specified mempool. */
bool os_mempool_is_sane(const struct os_mempool *mp);
/* Checks if a memory block was allocated from the specified mempool. */
int os_memblock_from(const struct os_mempool *mp, const void *block_addr);
/* Get a memory block from the pool */
void *os_memblock_get(struct os_mempool *mp);
/* Put the memory block back into the pool */
os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
#ifdef __cplusplus
}
#endif
#endif /* _OS_MEMPOOL_H_ */
+67
View File
@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_MUTEX_H_
#define _OS_MUTEX_H_
#include "os/os.h"
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_mutex
{
SLIST_HEAD(, os_task) mu_head; /* chain of waiting tasks */
uint8_t _pad;
uint8_t mu_prio; /* owner's default priority*/
uint16_t mu_level; /* call nesting level */
struct os_task *mu_owner; /* owners task */
};
/*
XXX: NOTES
-> Should we add a magic number or flag to the mutex structure so
that we know that this is a mutex? We can use it for double checking
that a proper mutex was passed in to the API.
-> What debug information should we add to this structure? Who last
acquired the mutex? File/line where it was released?
-> Should we add a name to the mutex?
-> Should we add a "os_mutex_inspect() api?
*/
/* XXX: api to create
os_mutex_inspect();
*/
/* Initialize a mutex */
os_error_t os_mutex_init(struct os_mutex *mu);
/* Release a mutex */
os_error_t os_mutex_release(struct os_mutex *mu);
/* Pend (wait) for a mutex */
os_error_t os_mutex_pend(struct os_mutex *mu, uint32_t timeout);
#ifdef __cplusplus
}
#endif
#endif /* _OS_MUTEX_H_ */
+64
View File
@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_SANITY_H
#define _OS_SANITY_H
#include <stdint.h>
#include "os/os_time.h"
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_sanity_check;
typedef int (*os_sanity_check_func_t)(struct os_sanity_check *, void *);
struct os_sanity_check {
os_time_t sc_checkin_last;
os_time_t sc_checkin_itvl;
os_sanity_check_func_t sc_func;
void *sc_arg;
SLIST_ENTRY(os_sanity_check) sc_next;
};
#define OS_SANITY_CHECK_SETFUNC(__sc, __f, __arg, __itvl) \
(__sc)->sc_func = (__f); \
(__sc)->sc_arg = (__arg); \
(__sc)->sc_checkin_itvl = (__itvl) * OS_TICKS_PER_SEC;
int os_sanity_init(void);
void os_sanity_run(void);
struct os_task;
int os_sanity_task_checkin(struct os_task *);
int os_sanity_check_init(struct os_sanity_check *);
int os_sanity_check_register(struct os_sanity_check *);
int os_sanity_check_reset(struct os_sanity_check *);
#ifdef __cplusplus
}
#endif
#endif /* _OS_SANITY_H */
+54
View File
@@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_SCHED_H
#define _OS_SCHED_H
#include "os/os_task.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_task;
TAILQ_HEAD(os_task_list, os_task);
extern struct os_task *g_current_task;
extern struct os_task_list g_os_run_list;
extern struct os_task_list g_os_sleep_list;
void os_sched_ctx_sw_hook(struct os_task *);
struct os_task *os_sched_get_current_task(void);
void os_sched_set_current_task(struct os_task *);
struct os_task *os_sched_next_task(void);
void os_sched(struct os_task *);
void os_sched_os_timer_exp(void);
os_error_t os_sched_insert(struct os_task *);
int os_sched_sleep(struct os_task *, os_time_t nticks);
int os_sched_wakeup(struct os_task *);
int os_sched_remove(struct os_task *);
void os_sched_resort(struct os_task *);
os_time_t os_sched_wakeup_ticks(os_time_t now);
#ifdef __cplusplus
}
#endif
#endif /* _OS_SCHED_H */
+66
View File
@@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_SEM_H_
#define _OS_SEM_H_
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_sem
{
SLIST_HEAD(, os_task) sem_head; /* chain of waiting tasks */
uint16_t _pad;
uint16_t sem_tokens; /* # of tokens */
};
/*
XXX: NOTES
-> Should we add a magic number or flag to the semaphore structure so
that we know that this is a semaphore? We can use it for double checking
that a proper semaphore was passed in to the API.
-> What debug information should we add to this structure? Who last
acquired the semaphore? File/line where it was released?
-> Should we add a name to the semaphore?
-> Should we add a "os_sem_inspect() api, like ucos?
*/
/* Create a semaphore */
os_error_t os_sem_init(struct os_sem *sem, uint16_t tokens);
/* Release a semaphore */
os_error_t os_sem_release(struct os_sem *sem);
/* Pend (wait) for a semaphore */
os_error_t os_sem_pend(struct os_sem *sem, uint32_t timeout);
/* Get current semaphore's count */
static inline uint16_t os_sem_get_count(struct os_sem *sem)
{
return sem->sem_tokens;
}
#ifdef __cplusplus
}
#endif
#endif /* _OS_SEM_H_ */
+128
View File
@@ -0,0 +1,128 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_TASK_H
#define _OS_TASK_H
#include "os/os.h"
#include "os/os_sanity.h"
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
/* The highest and lowest task priorities */
#define OS_TASK_PRI_HIGHEST (0)
#define OS_TASK_PRI_LOWEST (0xff)
/*
* Generic "object" structure. All objects that a task can wait on must
* have a SLIST_HEAD(, os_task) head_name as the first element in the object
* structure. The element 'head_name' can be any name. See os_mutex.h or
* os_sem.h for an example.
*/
struct os_task_obj {
SLIST_HEAD(, os_task) obj_head; /* chain of waiting tasks */
};
/* Task states */
typedef enum os_task_state {
OS_TASK_READY = 1,
OS_TASK_SLEEP = 2,
} os_task_state_t;
/* Task flags */
#define OS_TASK_FLAG_NO_TIMEOUT (0x01U)
#define OS_TASK_FLAG_SEM_WAIT (0x02U)
#define OS_TASK_FLAG_MUTEX_WAIT (0x04U)
#define OS_TASK_FLAG_EVQ_WAIT (0x08U)
typedef void (*os_task_func_t)(void *);
#define OS_TASK_MAX_NAME_LEN (32)
struct os_task {
os_stack_t *t_stackptr;
os_stack_t *t_stacktop;
uint16_t t_stacksize;
uint8_t t_taskid;
uint8_t t_prio;
uint8_t t_state;
uint8_t t_flags;
uint8_t t_lockcnt;
uint8_t t_pad;
const char *t_name;
os_task_func_t t_func;
void *t_arg;
void *t_obj;
struct os_sanity_check t_sanity_check;
os_time_t t_next_wakeup;
os_time_t t_run_time;
uint32_t t_ctx_sw_cnt;
/* Global list of all tasks, irrespective of run or sleep lists */
STAILQ_ENTRY(os_task) t_os_task_list;
/* Used to chain task to either the run or sleep list */
TAILQ_ENTRY(os_task) t_os_list;
/* Used to chain task to an object such as a semaphore or mutex */
SLIST_ENTRY(os_task) t_obj_list;
};
STAILQ_HEAD(os_task_stailq, os_task);
extern struct os_task_stailq g_os_task_list;
int os_task_init(struct os_task *, const char *, os_task_func_t, void *,
uint8_t, os_time_t, os_stack_t *, uint16_t);
int os_task_remove(struct os_task *t);
uint8_t os_task_count(void);
struct os_task_info {
uint8_t oti_prio;
uint8_t oti_taskid;
uint8_t oti_state;
uint16_t oti_stkusage;
uint16_t oti_stksize;
uint32_t oti_cswcnt;
uint32_t oti_runtime;
os_time_t oti_last_checkin;
os_time_t oti_next_checkin;
char oti_name[OS_TASK_MAX_NAME_LEN];
};
struct os_task *os_task_info_get_next(const struct os_task *,
struct os_task_info *);
#ifdef __cplusplus
}
#endif
#endif /* _OS_TASK_H */
+33
View File
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_OS_TEST_
#define H_OS_TEST_
#ifdef __cplusplus
extern "C" {
#endif
int os_test_all(void);
#ifdef __cplusplus
}
#endif
#endif
+120
View File
@@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
* $FreeBSD$
*/
#ifndef _OS_TIME_H
#define _OS_TIME_H
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef UINT32_MAX
#define UINT32_MAX 0xFFFFFFFFU
#endif
typedef uint32_t os_time_t;
typedef int32_t os_stime_t;
#define OS_TIME_MAX UINT32_MAX
/* Used to wait forever for events and mutexs */
#define OS_TIMEOUT_NEVER (UINT32_MAX)
os_time_t os_time_get(void);
void os_time_advance(int ticks);
void os_time_delay(int32_t osticks);
#define OS_TIME_TICK_LT(__t1, __t2) ((os_stime_t) ((__t1) - (__t2)) < 0)
#define OS_TIME_TICK_GT(__t1, __t2) ((os_stime_t) ((__t1) - (__t2)) > 0)
#define OS_TIME_TICK_GEQ(__t1, __t2) ((os_stime_t) ((__t1) - (__t2)) >= 0)
struct os_timeval {
int64_t tv_sec; /* seconds since Jan 1 1970 */
int32_t tv_usec; /* microseconds within the second */
};
struct os_timezone {
int16_t tz_minuteswest; /* with respect to GMT */
int16_t tz_dsttime; /* daylight savings time correction (if any) */
};
#define os_timeradd(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
if ((vvp)->tv_usec >= 1000000) { \
(vvp)->tv_sec++; \
(vvp)->tv_usec -= 1000000; \
} \
} while (0)
#define os_timersub(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
if ((vvp)->tv_usec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_usec += 1000000; \
} \
} while (0)
int os_settimeofday(struct os_timeval *utctime, struct os_timezone *tz);
int os_gettimeofday(struct os_timeval *utctime, struct os_timezone *tz);
int64_t os_get_uptime_usec(void);
int os_time_ms_to_ticks(uint32_t ms, uint32_t *out_ticks);
#ifdef __cplusplus
}
#endif
#endif /* _OS_TIME_H */
+84
View File
@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 OS_TRACE_API_H
#define OS_TRACE_API_H
#include <stdint.h>
#include "syscfg/syscfg.h"
#include "os/os.h"
#define OS_TRACE_ID_OFFSET (32u)
#define OS_TRACE_ID_EVQ_PUT (1u + OS_TRACE_ID_OFFSET)
#define OS_TRACE_ID_EVQ_GET (2u + OS_TRACE_ID_OFFSET)
#define OS_TRACE_ID_MUTEX_INIT (3u + OS_TRACE_ID_OFFSET)
#define OS_TRACE_ID_MUTEX_RELEASE (4u + OS_TRACE_ID_OFFSET)
#define OS_TRACE_ID_MUTEX_PEND (5u + OS_TRACE_ID_OFFSET)
#if MYNEWT_VAL(OS_SYSVIEW)
void os_trace_enter_isr(void);
void os_trace_exit_isr(void);
void os_trace_exit_isr_to_scheduler(void);
void os_trace_task_info(const struct os_task *p_task);
void os_trace_task_create(uint32_t task_id);
void os_trace_task_start_exec(uint32_t task_id);
void os_trace_task_stop_exec(void);
void os_trace_task_start_ready(uint32_t task_id);
void os_trace_task_stop_ready(uint32_t task_id, unsigned reason);
void os_trace_idle(void);
void os_trace_void(unsigned id);
void os_trace_u32(unsigned id, uint32_t para0);
void os_trace_u32x2(unsigned id, uint32_t para0, uint32_t para1);
void os_trace_u32x3(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2);
void os_trace_u32x4(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3);
void os_trace_u32x5(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3, uint32_t para4);
void os_trace_enter_timer(uint32_t timer_id);
void os_trace_exit_timer(void);
void os_trace_end_call(unsigned id);
void os_trace_end_call_return_value(unsigned id, uint32_t return_value);
#else
static inline void os_trace_enter_isr(void){}
static inline void os_trace_exit_isr(void){}
static inline void os_trace_exit_isr_to_scheduler(void){}
static inline void os_trace_task_info(const struct os_task *p_task){}
static inline void os_trace_task_create(uint32_t task_id){}
static inline void os_trace_task_start_exec(uint32_t task_id){}
static inline void os_trace_task_stop_exec(void){}
static inline void os_trace_task_start_ready(uint32_t task_id){}
static inline void os_trace_task_stop_ready(uint32_t task_id, unsigned reason){}
static inline void os_trace_idle(void){}
static inline void os_trace_void(unsigned id){}
static inline void os_trace_u32(unsigned id, uint32_t para0){}
static inline void os_trace_u32x2(unsigned id, uint32_t para0, uint32_t para1){}
static inline void os_trace_u32x3(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2){}
static inline void os_trace_u32x4(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3){}
static inline void os_trace_u32x5(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3, uint32_t para4){}
static inline void os_trace_enter_timer(uint32_t timer_id){}
static inline void os_trace_exit_timer(void){}
static inline void os_trace_end_call(unsigned id){}
static inline void os_trace_end_call_return_value(unsigned id, uint32_t return_value){}
#endif
#endif
+522
View File
@@ -0,0 +1,522 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS 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.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $
*/
#ifndef _QUEUE_H_
#define _QUEUE_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* This file defines five types of data structures: singly-linked lists,
* singly-linked tail queues, lists, tail queues, and circular queues.
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A singly-linked tail queue is headed by a pair of pointers, one to the
* head of the list and the other to the tail of the list. The elements are
* singly linked for minimum space and pointer manipulation overhead at the
* expense of O(n) removal for arbitrary elements. New elements can be added
* to the list after an existing element, at the head of the list, or at the
* end of the list. Elements being removed from the head of the tail queue
* should use the explicit macro for this purpose for optimum efficiency.
* A singly-linked tail queue may only be traversed in the forward direction.
* Singly-linked tail queues are ideal for applications with large datasets
* and few or no removals or for implementing a FIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*
*
* SLIST LIST STAILQ TAILQ CIRCLEQ
* _HEAD + + + + +
* _HEAD_INITIALIZER + + + + +
* _ENTRY + + + + +
* _INIT + + + + +
* _EMPTY + + + + +
* _FIRST + + + + +
* _NEXT + + + + +
* _PREV - - - + +
* _LAST - - + + +
* _FOREACH + + + + +
* _FOREACH_REVERSE - - - + +
* _INSERT_HEAD + + + + +
* _INSERT_BEFORE - + - + +
* _INSERT_AFTER + + + + +
* _INSERT_TAIL - - + + +
* _REMOVE_HEAD + - + - -
* _REMOVE + + + + +
*
*/
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = \
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
} \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY(head) ? \
NULL : \
((struct type *) \
((char *)((head)->stqh_last) - offsetof(struct type, field))))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD(head, field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
if ((STAILQ_NEXT(curelm, field) = \
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
} \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_REMOVE(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0)
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* Tail queue functions.
*/
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
} while (0)
/*
* Circular queue declarations.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ (void *)&(head), (void *)&(head) }
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue functions.
*/
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_FOREACH(var, head, field) \
for ((var) = CIRCLEQ_FIRST((head)); \
(var) != (void *)(head) || ((var) = NULL); \
(var) = CIRCLEQ_NEXT((var), field))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for ((var) = CIRCLEQ_LAST((head)); \
(var) != (void *)(head) || ((var) = NULL); \
(var) = CIRCLEQ_PREV((var), field))
#define CIRCLEQ_INIT(head) do { \
CIRCLEQ_FIRST((head)) = (void *)(head); \
CIRCLEQ_LAST((head)) = (void *)(head); \
} while (0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
CIRCLEQ_PREV((elm), field) = (listelm); \
if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \
else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
CIRCLEQ_NEXT((listelm), field) = (elm); \
} while (0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (listelm); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \
else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
CIRCLEQ_PREV((listelm), field) = (elm); \
} while (0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
CIRCLEQ_PREV((elm), field) = (void *)(head); \
if (CIRCLEQ_LAST((head)) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \
else \
CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
CIRCLEQ_FIRST((head)) = (elm); \
} while (0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (void *)(head); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \
else \
CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
CIRCLEQ_LAST((head)) = (elm); \
} while (0)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
#define CIRCLEQ_REMOVE(head, elm, field) do { \
if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
CIRCLEQ_PREV((elm), field); \
if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
CIRCLEQ_NEXT((elm), field); \
} while (0)
#ifdef __cplusplus
}
#endif
#endif /* !_QUEUE_H_ */
+83
View File
@@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 __UTIL_STATS_H__
#define __UTIL_STATS_H__
#include <stdint.h>
#include "syscfg/syscfg.h"
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct stats_name_map {
uint16_t snm_off;
char *snm_name;
} __attribute__((packed));
struct stats_hdr {
char *s_name;
uint8_t s_size;
uint8_t s_cnt;
uint16_t s_pad1;
#if MYNEWT_VAL(STATS_NAMES)
const struct stats_name_map *s_map;
int s_map_cnt;
#endif
STAILQ_ENTRY(stats_hdr) s_next;
};
#define STATS_SECT_DECL(__name) \
struct stats_ ## __name
#define STATS_SECT_END };
#define STATS_SECT_START(__name) \
STATS_SECT_DECL(__name) {
#define STATS_SECT_VAR(__var)
#define STATS_HDR(__sectname)
#define STATS_SECT_ENTRY(__var)
#define STATS_SECT_ENTRY16(__var)
#define STATS_SECT_ENTRY32(__var)
#define STATS_SECT_ENTRY64(__var)
#define STATS_RESET(__var)
#define STATS_SIZE_INIT_PARMS(__sectvarname, __size) 0, 0
#define STATS_INC(__sectvarname, __var)
#define STATS_INCN(__sectvarname, __var, __n)
#define STATS_CLEAR(__sectvarname, __var)
#define STATS_NAME_START(__name)
#define STATS_NAME(__name, __entry)
#define STATS_NAME_END(__name)
#define STATS_NAME_INIT_PARMS(__name) NULL, 0
#define stats_init(...) 0
#define stats_register(name, shdr) 0
#define stats_init_and_reg(...) 0
#define stats_reset(shdr)
#ifdef __cplusplus
}
#endif
#endif /* __UTIL_STATS_H__ */
+128
View File
@@ -0,0 +1,128 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_SYSINIT_
#define H_SYSINIT_
#include <inttypes.h>
#include <assert.h>
#include "syscfg/syscfg.h"
#if MYNEWT_VAL(SPLIT_APPLICATION)
#include "split/split.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern uint8_t sysinit_active;
void sysinit_start(void);
void sysinit_end(void);
typedef void sysinit_panic_fn(const char *file, int line, const char *func,
const char *expr, const char *msg);
extern sysinit_panic_fn *sysinit_panic_cb;
void sysinit_panic_set(sysinit_panic_fn *panic_fn);
#if MYNEWT_VAL(SYSINIT_PANIC_MESSAGE)
#if MYNEWT_VAL(SYSINIT_PANIC_FILE_LINE)
#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(__FILE__, __LINE__, 0, 0, msg)
#else
#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(0, 0, 0, 0, msg)
#endif
#else
#if MYNEWT_VAL(SYSINIT_PANIC_FILE_LINE)
#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(__FILE__, __LINE__, 0, 0, 0)
#else
#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(0, 0, 0, 0, 0)
#endif
#endif
#define SYSINIT_PANIC() SYSINIT_PANIC_MSG(NULL)
#define SYSINIT_PANIC_ASSERT_MSG(rc, msg) do \
{ \
if (!(rc)) { \
SYSINIT_PANIC_MSG(msg); \
} \
} while (0)
#define SYSINIT_PANIC_ASSERT(rc) SYSINIT_PANIC_ASSERT_MSG(rc, NULL)
/**
* Asserts that system initialization is in progress. This macro is used to
* ensure packages don't get initialized a second time after system
* initialization has completed.
*/
#if MYNEWT_VAL(SYSINIT_CONSTRAIN_INIT)
#define SYSINIT_ASSERT_ACTIVE() assert(sysinit_active)
#else
#define SYSINIT_ASSERT_ACTIVE()
#endif
#if MYNEWT_VAL(SPLIT_LOADER)
/*** System initialization for loader (first stage of split image). */
void sysinit_loader(void);
#define sysinit() do \
{ \
sysinit_start(); \
sysinit_loader(); \
sysinit_end(); \
} while (0)
#elif MYNEWT_VAL(SPLIT_APPLICATION)
/*** System initialization for split-app (second stage of split image). */
void sysinit_app(void);
#define sysinit() do \
{ \
/* Record that a split app is running; imgmgt needs to know this. */ \
split_app_active_set(1); \
sysinit_start(); \
sysinit_app(); \
sysinit_end(); \
} while (0)
#else
/*** System initialization for a unified image (no split). */
void sysinit_app(void);
#define sysinit() do \
{ \
sysinit_start(); \
sysinit_app(); \
sysinit_end(); \
} while (0)
#endif
#ifdef __cplusplus
}
#endif
#endif
+245
View File
@@ -0,0 +1,245 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/os.h"
#include "mem/mem.h"
/**
* Mallocs a block of memory and initializes a mempool to use it.
*
* @param mempool The mempool to initialize.
* @param num_blocks The total number of memory blocks in the
* mempool.
* @param block_size The size of each mempool entry.
* @param name The name to give the mempool.
* @param out_buf On success, this points to the malloced memory.
* Pass NULL if you don't need this
* information.
*
* @return 0 on success;
* OS_ENOMEM on malloc failure;
* Other OS code on unexpected error.
*/
int
mem_malloc_mempool(struct os_mempool *mempool, int num_blocks, int block_size,
char *name, void **out_buf)
{
void *buf;
int rc;
block_size = OS_ALIGN(block_size, OS_ALIGNMENT);
if (num_blocks > 0) {
buf = malloc(OS_MEMPOOL_BYTES(num_blocks, block_size));
if (buf == NULL) {
return OS_ENOMEM;
}
} else {
buf = NULL;
}
rc = os_mempool_init(mempool, num_blocks, block_size, buf, name);
if (rc != 0) {
free(buf);
return rc;
}
if (out_buf != NULL) {
*out_buf = buf;
}
return 0;
}
/**
* Mallocs a block of memory and initializes an mbuf pool to use it. The
* specified block_size indicates the size of an mbuf acquired from the pool if
* it does not contain a pkthdr.
*
* @param mempool The mempool to initialize.
* @param mbuf_pool The mbuf pool to initialize.
* @param num_blocks The total number of mbufs in the pool.
* @param block_size The size of each mbuf.
* @param name The name to give the mempool.
* @param out_buf On success, this points to the malloced memory.
* Pass NULL if you don't need this
* information.
*
* @return 0 on success;
* OS_ENOMEM on malloc failure;
* Other OS code on unexpected error.
*/
int
mem_malloc_mbuf_pool(struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, char *name,
void **out_buf)
{
void *buf;
int rc;
block_size = OS_ALIGN(block_size + sizeof (struct os_mbuf), OS_ALIGNMENT);
rc = mem_malloc_mempool(mempool, num_blocks, block_size, name, &buf);
if (rc != 0) {
return rc;
}
rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks);
if (rc != 0) {
free(buf);
return rc;
}
if (out_buf != NULL) {
*out_buf = buf;
}
return 0;
}
/**
* Mallocs a block of memory and initializes an mbuf pool to use it. The
* specified block_size indicates the size of an mbuf acquired from the pool if
* it contains a pkthdr.
*
* @param mempool The mempool to initialize.
* @param mbuf_pool The mbuf pool to initialize.
* @param num_blocks The total number of mbufs in the pool.
* @param block_size The size of each mbuf.
* @param name The name to give the mempool.
* @param out_buf On success, this points to the malloced memory.
* Pass NULL if you don't need this
* information.
*
* @return 0 on success;
* OS_ENOMEM on malloc failure;
* Other OS code on unexpected error.
*/
int
mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, char *name,
void **out_buf)
{
int rc;
rc = mem_malloc_mbuf_pool(mempool, mbuf_pool, num_blocks,
block_size + sizeof (struct os_mbuf_pkthdr),
name, out_buf);
return rc;
}
int
mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, char *name)
{
int rc;
rc = os_mempool_init(mempool, num_blocks, block_size, mem, name);
if (rc != 0) {
return rc;
}
rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks);
if (rc != 0) {
return rc;
}
return 0;
}
/*
* Splits an appropriately-sized fragment from the front of an mbuf chain, as
* neeeded. If the length of the mbuf chain greater than specified maximum
* fragment size, a new mbuf is allocated, and data is moved from the source
* mbuf to the new mbuf. If the mbuf chain is small enough to fit in a single
* fragment, the source mbuf itself is returned unmodified, and the suplied
* pointer is set to NULL.
*
* This function is expected to be called in a loop until the entire mbuf chain
* has been consumed. For example:
*
* struct os_mbuf *frag;
* struct os_mbuf *rsp;
* // [...]
* while (rsp != NULL) {
* frag = mem_split_frag(&rsp, get_mtu(), frag_alloc, NULL);
* if (frag == NULL) {
* os_mbuf_free_chain(rsp);
* return SYS_ENOMEM;
* }
* send_packet(frag)
* }
*
* @param om The packet to fragment. Upon fragmentation,
* this mbuf is adjusted such that the
* fragment data is removed. If the packet
* constitutes a single fragment, this gets
* set to NULL on success.
* @param max_frag_sz The maximum payload size of a fragment.
* Typically this is the MTU of the
* connection.
* @param alloc_cb Points to a function that allocates an mbuf to
* hold a fragment. This function gets called
* before the source mbuf chain is modified,
* so it can safely inspect it.
* @param cb_arg Generic parameter that gets passed to the
* callback function.
*
* @return The next fragment to send on success;
* NULL on failure.
*/
struct os_mbuf *
mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
mem_frag_alloc_fn *alloc_cb, void *cb_arg)
{
struct os_mbuf *frag;
int rc;
if (OS_MBUF_PKTLEN(*om) <= max_frag_sz) {
/* Final fragment. */
frag = *om;
*om = NULL;
return frag;
}
/* Packet needs to be split. Allocate a new buffer for the fragment. */
frag = alloc_cb(max_frag_sz, cb_arg);
if (frag == NULL) {
goto err;
}
/* Move data from the front of the packet into the fragment mbuf. */
rc = os_mbuf_appendfrom(frag, *om, 0, max_frag_sz);
if (rc != 0) {
goto err;
}
os_mbuf_adj(*om, max_frag_sz);
/* Free unused portion of of source mbuf chain, if possible. */
*om = os_mbuf_trim_front(*om);
return frag;
err:
os_mbuf_free_chain(frag);
return NULL;
}
+65
View File
@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <stddef.h>
#include "os/os.h"
#include "sysinit/sysinit.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "services/ans/ble_svc_ans.h"
#include "services/ias/ble_svc_ias.h"
#include "services/lls/ble_svc_lls.h"
#include "services/tps/ble_svc_tps.h"
#include "controller/ble_ll.h"
void
nimble_init(void)
{
void os_msys_init(void);
void ble_hci_ram_pkg_init(void);
void ble_store_ram_init(void);
sysinit_start();
os_msys_init();
ble_hci_ram_pkg_init();
ble_hs_init();
ble_ll_init();
ble_svc_gap_init();
ble_svc_gatt_init();
ble_svc_ans_init();
ble_svc_ias_init();
ble_svc_lls_init();
ble_svc_tps_init();
ble_store_ram_init();
sysinit_end();
}
void
nimble_run(void)
{
while (1) {
struct os_event *ev;
ev = os_eventq_get(os_eventq_dflt_get());
assert(ev->ev_cb != NULL);
ev->ev_cb(ev);
}
}
+218
View File
@@ -0,0 +1,218 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/endian.h"
void
put_le16(void *buf, uint16_t x)
{
uint8_t *u8ptr;
u8ptr = buf;
u8ptr[0] = (uint8_t)x;
u8ptr[1] = (uint8_t)(x >> 8);
}
void
put_le32(void *buf, uint32_t x)
{
uint8_t *u8ptr;
u8ptr = buf;
u8ptr[0] = (uint8_t)x;
u8ptr[1] = (uint8_t)(x >> 8);
u8ptr[2] = (uint8_t)(x >> 16);
u8ptr[3] = (uint8_t)(x >> 24);
}
void
put_le64(void *buf, uint64_t x)
{
uint8_t *u8ptr;
u8ptr = buf;
u8ptr[0] = (uint8_t)x;
u8ptr[1] = (uint8_t)(x >> 8);
u8ptr[2] = (uint8_t)(x >> 16);
u8ptr[3] = (uint8_t)(x >> 24);
u8ptr[4] = (uint8_t)(x >> 32);
u8ptr[5] = (uint8_t)(x >> 40);
u8ptr[6] = (uint8_t)(x >> 48);
u8ptr[7] = (uint8_t)(x >> 56);
}
uint16_t
get_le16(const void *buf)
{
const uint8_t *u8ptr;
uint16_t x;
u8ptr = buf;
x = u8ptr[0];
x |= (uint16_t)u8ptr[1] << 8;
return x;
}
uint32_t
get_le32(const void *buf)
{
const uint8_t *u8ptr;
uint32_t x;
u8ptr = buf;
x = u8ptr[0];
x |= (uint32_t)u8ptr[1] << 8;
x |= (uint32_t)u8ptr[2] << 16;
x |= (uint32_t)u8ptr[3] << 24;
return x;
}
uint64_t
get_le64(const void *buf)
{
const uint8_t *u8ptr;
uint64_t x;
u8ptr = buf;
x = u8ptr[0];
x |= (uint64_t)u8ptr[1] << 8;
x |= (uint64_t)u8ptr[2] << 16;
x |= (uint64_t)u8ptr[3] << 24;
x |= (uint64_t)u8ptr[4] << 32;
x |= (uint64_t)u8ptr[5] << 40;
x |= (uint64_t)u8ptr[6] << 48;
x |= (uint64_t)u8ptr[7] << 56;
return x;
}
void
put_be16(void *buf, uint16_t x)
{
uint8_t *u8ptr;
u8ptr = buf;
u8ptr[0] = (uint8_t)(x >> 8);
u8ptr[1] = (uint8_t)x;
}
void
put_be32(void *buf, uint32_t x)
{
uint8_t *u8ptr;
u8ptr = buf;
u8ptr[0] = (uint8_t)(x >> 24);
u8ptr[1] = (uint8_t)(x >> 16);
u8ptr[2] = (uint8_t)(x >> 8);
u8ptr[3] = (uint8_t)x;
}
void
put_be64(void *buf, uint64_t x)
{
uint8_t *u8ptr;
u8ptr = buf;
u8ptr[0] = (uint8_t)(x >> 56);
u8ptr[1] = (uint8_t)(x >> 48);
u8ptr[2] = (uint8_t)(x >> 40);
u8ptr[3] = (uint8_t)(x >> 32);
u8ptr[4] = (uint8_t)(x >> 24);
u8ptr[5] = (uint8_t)(x >> 16);
u8ptr[6] = (uint8_t)(x >> 8);
u8ptr[7] = (uint8_t)x;
}
uint16_t
get_be16(const void *buf)
{
const uint8_t *u8ptr;
uint16_t x;
u8ptr = buf;
x = (uint16_t)u8ptr[0] << 8;
x |= u8ptr[1];
return x;
}
uint32_t
get_be32(const void *buf)
{
const uint8_t *u8ptr;
uint32_t x;
u8ptr = buf;
x = (uint32_t)u8ptr[0] << 24;
x |= (uint32_t)u8ptr[1] << 16;
x |= (uint32_t)u8ptr[2] << 8;
x |= u8ptr[3];
return x;
}
uint64_t
get_be64(const void *buf)
{
const uint8_t *u8ptr;
uint64_t x;
u8ptr = buf;
x = (uint64_t)u8ptr[0] << 56;
x |= (uint64_t)u8ptr[1] << 48;
x |= (uint64_t)u8ptr[2] << 40;
x |= (uint64_t)u8ptr[3] << 32;
x |= (uint64_t)u8ptr[4] << 24;
x |= (uint64_t)u8ptr[5] << 16;
x |= (uint64_t)u8ptr[6] << 8;
x |= u8ptr[7];
return x;
}
void
swap_in_place(void *buf, int len)
{
uint8_t *u8ptr;
uint8_t tmp;
int i;
int j;
u8ptr = buf;
for (i = 0, j = len - 1; i < j; i++, j--) {
tmp = u8ptr[i];
u8ptr[i] = u8ptr[j];
u8ptr[j] = tmp;
}
}
/* swap octets */
void
swap_buf(uint8_t *dst, const uint8_t *src, int len)
{
int i;
for (i = 0; i < len; i++) {
dst[len - 1 - i] = src[i];
}
}
+240
View File
@@ -0,0 +1,240 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "sysinit/sysinit.h"
#include "os/os.h"
#include "os/queue.h"
#include "os/os_dev.h"
#include "os/os_trace_api.h"
#include "hal/hal_os_tick.h"
#include "hal/hal_bsp.h"
#include "hal/hal_watchdog.h"
#include <assert.h>
#include "../os/os_priv.h"
/**
* @defgroup OSKernel Operating System Kernel
* @brief This section contains documentation for the core operating system kernel
* of Apache Mynewt.
* @{
* @addtogroup OSGeneral General Functions
* @{
*/
struct os_task g_idle_task;
os_stack_t g_idle_task_stack[OS_STACK_ALIGN(OS_IDLE_STACK_SIZE)];
uint32_t g_os_idle_ctr;
static struct os_task os_main_task;
static os_stack_t os_main_stack[OS_STACK_ALIGN(OS_MAIN_STACK_SIZE)];
/* Default zero. Set by the architecture specific code when os is started.
*/
int g_os_started;
#ifdef ARCH_sim
#define MIN_IDLE_TICKS 1
#else
#define MIN_IDLE_TICKS (100 * OS_TICKS_PER_SEC / 1000) /* 100 msec */
#endif
#define MAX_IDLE_TICKS (600 * OS_TICKS_PER_SEC) /* 10 minutes */
/**
* Idle operating system task, runs when no other tasks are running.
* The idle task operates in tickless mode, which means it looks for
* the next time an event in the system needs to run, and then tells
* the architecture specific functions to sleep until that time.
*
* @param arg unused
*/
void
os_idle_task(void *arg)
{
os_sr_t sr;
os_time_t now;
os_time_t iticks, sticks, cticks;
os_time_t sanity_last;
os_time_t sanity_itvl_ticks;
sanity_itvl_ticks = (MYNEWT_VAL(SANITY_INTERVAL) * OS_TICKS_PER_SEC) / 1000;
sanity_last = 0;
hal_watchdog_tickle();
while (1) {
++g_os_idle_ctr;
now = os_time_get();
if (OS_TIME_TICK_GT(now, sanity_last + sanity_itvl_ticks)) {
os_sanity_run();
/* Tickle the watchdog after successfully running sanity */
hal_watchdog_tickle();
sanity_last = now;
}
OS_ENTER_CRITICAL(sr);
now = os_time_get();
sticks = os_sched_wakeup_ticks(now);
cticks = os_callout_wakeup_ticks(now);
iticks = min(sticks, cticks);
/* Wakeup in time to run sanity as well from the idle context,
* as the idle task does not schedule itself.
*/
iticks = min(iticks, ((sanity_last + sanity_itvl_ticks) - now));
if (iticks < MIN_IDLE_TICKS) {
iticks = 0;
} else if (iticks > MAX_IDLE_TICKS) {
iticks = MAX_IDLE_TICKS;
} else {
/* NOTHING */
}
/* Tell the architecture specific support to put the processor to sleep
* for 'n' ticks.
*/
os_trace_idle();
os_tick_idle(iticks);
OS_EXIT_CRITICAL(sr);
}
}
/**
* Has the operating system started.
*
* @return 1 if the operating system has started, 0 if it hasn't
*/
int
os_started(void)
{
return (g_os_started);
}
static void
os_main(void *arg)
{
int (*fn)(int argc, char **argv) = arg;
#if !MYNEWT_VAL(SELFTEST)
fn(0, NULL);
#else
(void)fn;
while (1) {
os_eventq_run(os_eventq_dflt_get());
}
#endif
assert(0);
}
void
os_init_idle_task(void)
{
int rc;
rc = os_task_init(&g_idle_task, "idle", os_idle_task, NULL,
OS_IDLE_PRIO, OS_WAIT_FOREVER, g_idle_task_stack,
OS_STACK_ALIGN(OS_IDLE_STACK_SIZE));
assert(rc == 0);
/* Initialize sanity */
rc = os_sanity_init();
assert(rc == 0);
assert(MYNEWT_VAL(WATCHDOG_INTERVAL) - 200 > MYNEWT_VAL(SANITY_INTERVAL));
rc = hal_watchdog_init(MYNEWT_VAL(WATCHDOG_INTERVAL));
assert(rc == 0);
}
/**
* Initialize the operating system, calls into the architecture specific
* support to initialize the operating system.
*/
void
os_init(int (*main_fn)(int argc, char **arg))
{
os_error_t err;
TAILQ_INIT(&g_callout_list);
STAILQ_INIT(&g_os_task_list);
os_eventq_init(os_eventq_dflt_get());
/* Initialize device list. */
os_dev_reset();
err = os_arch_os_init();
assert(err == OS_OK);
if (main_fn) {
err = os_task_init(&os_main_task, "main", os_main, main_fn,
OS_MAIN_TASK_PRIO, OS_WAIT_FOREVER, os_main_stack,
OS_STACK_ALIGN(OS_MAIN_STACK_SIZE));
assert(err == 0);
}
/* Call bsp related OS initializations */
hal_bsp_init();
err = (os_error_t) os_dev_initialize_all(OS_DEV_INIT_PRIMARY);
assert(err == OS_OK);
err = (os_error_t) os_dev_initialize_all(OS_DEV_INIT_SECONDARY);
assert(err == OS_OK);
}
/**
* Start the operating system, calls into the architecture specific support
* to start the operating system.
*/
void
os_start(void)
{
#if MYNEWT_VAL(OS_SCHEDULING)
os_error_t err;
/* Enable the watchdog prior to starting the OS */
hal_watchdog_enable();
err = os_arch_os_start();
assert(err == OS_OK);
#else
assert(0);
#endif
}
void
os_pkg_init(void)
{
os_error_t err;
/* Ensure this function only gets called by sysinit. */
SYSINIT_ASSERT_ACTIVE();
err = os_dev_initialize_all(OS_DEV_INIT_KERNEL);
assert(err == OS_OK);
os_msys_init();
}
/**
* }@ General OS functions
* }@ OS Kernel
*/
+230
View File
@@ -0,0 +1,230 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <assert.h>
#include <string.h>
#include "../os/os_priv.h"
#include "os/os.h"
/**
* @addtogroup OSKernel
* @{
* @defgroup OSCallouts Event Timers (Callouts)
* @{
*/
struct os_callout_list g_callout_list;
/**
* Initialize a callout.
*
* Callouts are used to schedule events in the future onto a task's event
* queue. Callout timers are scheduled using the os_callout_reset()
* function. When the timer expires, an event is posted to the event
* queue specified in os_callout_init(). The event argument given here
* is posted in the ev_arg field of that event.
*
* @param c The callout to initialize
* @param evq The event queue to post an OS_EVENT_T_TIMER event to
* @param timo_func The function to call on this callout for the host task
* used to provide multiple timer events to a task
* (this can be NULL.)
* @param ev_arg The argument to provide to the event when posting the
* timer.
*/
void os_callout_init(struct os_callout *c, struct os_eventq *evq,
os_event_fn *ev_cb, void *ev_arg)
{
memset(c, 0, sizeof(*c));
c->c_ev.ev_cb = ev_cb;
c->c_ev.ev_arg = ev_arg;
c->c_evq = evq;
}
/**
* Stop the callout from firing off, any pending events will be cleared.
*
* @param c The callout to stop
*/
void
os_callout_stop(struct os_callout *c)
{
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
if (os_callout_queued(c)) {
TAILQ_REMOVE(&g_callout_list, c, c_next);
c->c_next.tqe_prev = NULL;
}
if (c->c_evq) {
os_eventq_remove(c->c_evq, &c->c_ev);
}
OS_EXIT_CRITICAL(sr);
}
/**
* Reset the callout to fire off in 'ticks' ticks.
*
* @param c The callout to reset
* @param ticks The number of ticks to wait before posting an event
*
* @return 0 on success, non-zero on failure
*/
int
os_callout_reset(struct os_callout *c, int32_t ticks)
{
struct os_callout *entry;
os_sr_t sr;
int rc;
if (ticks < 0) {
rc = OS_EINVAL;
goto err;
}
OS_ENTER_CRITICAL(sr);
os_callout_stop(c);
if (ticks == 0) {
ticks = 1;
}
c->c_ticks = os_time_get() + ticks;
entry = NULL;
TAILQ_FOREACH(entry, &g_callout_list, c_next) {
if (OS_TIME_TICK_LT(c->c_ticks, entry->c_ticks)) {
break;
}
}
if (entry) {
TAILQ_INSERT_BEFORE(entry, c, c_next);
} else {
TAILQ_INSERT_TAIL(&g_callout_list, c, c_next);
}
OS_EXIT_CRITICAL(sr);
return (0);
err:
return (rc);
}
/**
* This function is called by the OS in the time tick. It searches the list
* of callouts, and sees if any of them are ready to run. If they are ready
* to run, it posts an event for each callout that's ready to run,
* to the event queue provided to os_callout_init().
*/
void
os_callout_tick(void)
{
os_sr_t sr;
struct os_callout *c;
uint32_t now;
now = os_time_get();
while (1) {
OS_ENTER_CRITICAL(sr);
c = TAILQ_FIRST(&g_callout_list);
if (c) {
if (OS_TIME_TICK_GEQ(now, c->c_ticks)) {
TAILQ_REMOVE(&g_callout_list, c, c_next);
c->c_next.tqe_prev = NULL;
} else {
c = NULL;
}
}
OS_EXIT_CRITICAL(sr);
if (c) {
if (c->c_evq) {
os_eventq_put(c->c_evq, &c->c_ev);
} else {
c->c_ev.ev_cb(&c->c_ev);
}
} else {
break;
}
}
}
/*
* Returns the number of ticks to the first pending callout. If there are no
* pending callouts then return OS_TIMEOUT_NEVER instead.
*
* @param now The time now
*
* @return Number of ticks to first pending callout
*/
os_time_t
os_callout_wakeup_ticks(os_time_t now)
{
os_time_t rt;
struct os_callout *c;
OS_ASSERT_CRITICAL();
c = TAILQ_FIRST(&g_callout_list);
if (c != NULL) {
if (OS_TIME_TICK_GEQ(c->c_ticks, now)) {
rt = c->c_ticks - now;
} else {
rt = 0; /* callout time is in the past */
}
} else {
rt = OS_TIMEOUT_NEVER;
}
return (rt);
}
/*
* Returns the number of ticks which remains to callout..
*
* @param c callout
* @param now The time now
*
* @return Number of ticks to first pending callout
*/
os_time_t os_callout_remaining_ticks(struct os_callout *c, os_time_t now)
{
os_time_t rt;
OS_ASSERT_CRITICAL();
if (OS_TIME_TICK_GEQ(c->c_ticks, now)) {
rt = c->c_ticks - now;
} else {
rt = 0; /* callout time is in the past */
}
return rt;
}
/**
* @} Callout Timers
* @} OS Kernel
*/
+215
View File
@@ -0,0 +1,215 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <stdint.h>
#include <assert.h>
#include "os/os.h"
#include "os/os_cputime.h"
/**
* @addtogroup OSKernel Operating System Kernel
* @{
* @defgroup OSCPUTime High Resolution Timers
* @{
*/
#if defined(OS_CPUTIME_FREQ_HIGH)
struct os_cputime_data g_os_cputime;
#endif
/**
* os cputime init
*
* Initialize the cputime module. This must be called after os_init is called
* and before any other timer API are used. This should be called only once
* and should be called before the hardware timer is used.
*
* @param clock_freq The desired cputime frequency, in hertz (Hz).
*
* @return int 0 on success; -1 on error.
*/
int
os_cputime_init(uint32_t clock_freq)
{
int rc;
/* Set the ticks per microsecond. */
#if defined(OS_CPUTIME_FREQ_HIGH)
g_os_cputime.ticks_per_usec = clock_freq / 1000000U;
#endif
rc = hal_timer_config(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM), clock_freq);
return rc;
}
/**
* os cputime delay ticks
*
* Wait until the number of ticks has elapsed. This is a blocking delay.
*
* @param ticks The number of ticks to wait.
*/
void
os_cputime_delay_ticks(uint32_t ticks)
{
uint32_t until;
until = os_cputime_get32() + ticks;
while ((int32_t)(os_cputime_get32() - until) < 0) {
/* Loop here till finished */
}
}
#if !defined(OS_CPUTIME_FREQ_PWR2)
/**
* os cputime delay nsecs
*
* Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
*
* @param nsecs The number of nanoseconds to wait.
*/
void
os_cputime_delay_nsecs(uint32_t nsecs)
{
uint32_t ticks;
ticks = os_cputime_nsecs_to_ticks(nsecs);
os_cputime_delay_ticks(ticks);
}
#endif
/**
* os cputime delay usecs
*
* Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
*
* @param usecs The number of usecs to wait.
*/
void
os_cputime_delay_usecs(uint32_t usecs)
{
uint32_t ticks;
ticks = os_cputime_usecs_to_ticks(usecs);
os_cputime_delay_ticks(ticks);
}
/**
* os cputime timer init
*
* @param timer The timer to initialize. Cannot be NULL.
* @param fp The timer callback function. Cannot be NULL.
* @param arg Pointer to data object to pass to timer.
*/
void
os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp, void *arg)
{
assert(timer != NULL);
assert(fp != NULL);
hal_timer_set_cb(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM), timer, fp, arg);
}
/**
* os cputime timer start
*
* Start a cputimer that will expire at 'cputime'. If cputime has already
* passed, the timer callback will still be called (at interrupt context).
*
* NOTE: This must be called when the timer is stopped.
*
* @param timer Pointer to timer to start. Cannot be NULL.
* @param cputime The cputime at which the timer should expire.
*
* @return int 0 on success; EINVAL if timer already started or timer struct
* invalid
*
*/
int
os_cputime_timer_start(struct hal_timer *timer, uint32_t cputime)
{
int rc;
rc = hal_timer_start_at(timer, cputime);
return rc;
}
/**
* os cputimer timer relative
*
* Sets a cpu timer that will expire 'usecs' microseconds from the current
* cputime.
*
* NOTE: This must be called when the timer is stopped.
*
* @param timer Pointer to timer. Cannot be NULL.
* @param usecs The number of usecs from now at which the timer will expire.
*
* @return int 0 on success; EINVAL if timer already started or timer struct
* invalid
*/
int
os_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs)
{
int rc;
uint32_t cputime;
assert(timer != NULL);
cputime = os_cputime_get32() + os_cputime_usecs_to_ticks(usecs);
rc = hal_timer_start_at(timer, cputime);
return rc;
}
/**
* os cputime timer stop
*
* Stops a cputimer from running. The timer is removed from the timer queue
* and interrupts are disabled if no timers are left on the queue. Can be
* called even if timer is not running.
*
* @param timer Pointer to cputimer to stop. Cannot be NULL.
*/
void
os_cputime_timer_stop(struct hal_timer *timer)
{
hal_timer_stop(timer);
}
/**
* os cputime get32
*
* Returns current value of cputime.
*
* @return uint32_t cputime
*/
uint32_t
os_cputime_get32(void)
{
uint32_t cpu_time;
cpu_time = hal_timer_read(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM));
return cpu_time;
}
/**
* @} OSCPUTime
* @} OSKernel
*/
+52
View File
@@ -0,0 +1,52 @@
#include "os/os_cputime.h"
/**
* This module implements cputime functionality for timers whose frequency is
* exactly 1 MHz.
*/
#if defined(OS_CPUTIME_FREQ_1MHZ)
/**
* @addtogroup OSKernel Operating System Kernel
* @{
* @defgroup OSCPUTime High Resolution Timers
* @{
*/
/**
* os cputime nsecs to ticks
*
* Converts the given number of nanoseconds into cputime ticks.
*
* @param usecs The number of nanoseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'nsecs'
*/
uint32_t
os_cputime_nsecs_to_ticks(uint32_t nsecs)
{
return (nsecs + 999) / 1000;
}
/**
* os cputime ticks to nsecs
*
* Convert the given number of ticks into nanoseconds.
*
* @param ticks The number of ticks to convert to nanoseconds.
*
* @return uint32_t The number of nanoseconds corresponding to 'ticks'
*/
uint32_t
os_cputime_ticks_to_nsecs(uint32_t ticks)
{
return ticks * 1000;
}
/**
* @} OSCPUTime
* @} OSKernel
*/
#endif
+84
View File
@@ -0,0 +1,84 @@
#include "os/os_cputime.h"
/**
* This module implements cputime functionality for timers whose frequency is
* greater than 1 MHz.
*/
#if defined(OS_CPUTIME_FREQ_HIGH)
/**
* @addtogroup OSKernel Operating System Kernel
* @{
* @defgroup OSCPUTime High Resolution Timers
* @{
*/
/**
* os cputime usecs to ticks
*
* Converts the given number of microseconds into cputime ticks.
*
* @param usecs The number of microseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'usecs'
*/
uint32_t
os_cputime_usecs_to_ticks(uint32_t usecs)
{
return usecs * g_os_cputime.ticks_per_usec;
}
/**
* cputime ticks to usecs
*
* Convert the given number of ticks into microseconds.
*
* @param ticks The number of ticks to convert to microseconds.
*
* @return uint32_t The number of microseconds corresponding to 'ticks'
*/
uint32_t
os_cputime_ticks_to_usecs(uint32_t ticks)
{
return (ticks + g_os_cputime.ticks_per_usec - 1) /
g_os_cputime.ticks_per_usec;
}
/**
* os cputime nsecs to ticks
*
* Converts the given number of nanoseconds into cputime ticks.
*
* @param usecs The number of nanoseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'nsecs'
*/
uint32_t
os_cputime_nsecs_to_ticks(uint32_t nsecs)
{
return (nsecs * g_os_cputime.ticks_per_usec + 999) / 1000;
}
/**
* os cputime ticks to nsecs
*
* Convert the given number of ticks into nanoseconds.
*
* @param ticks The number of ticks to convert to nanoseconds.
*
* @return uint32_t The number of nanoseconds corresponding to 'ticks'
*/
uint32_t
os_cputime_ticks_to_nsecs(uint32_t ticks)
{
return (ticks * 1000 + g_os_cputime.ticks_per_usec - 1) /
g_os_cputime.ticks_per_usec;
}
/**
* @} OSCPUTime
* @} OSKernel
*/
#endif
+90
View File
@@ -0,0 +1,90 @@
#include "os/os_cputime.h"
/**
* This module implements cputime functionality for timers for which:
* a. freq is a power of 2 Hz, and
* b. 256 Hz <= freq < 1 MHz
*/
#if defined(OS_CPUTIME_FREQ_PWR2)
/**
* @addtogroup OSKernel Operating System Kernel
* @{
* @defgroup OSCPUTime High Resolution Timers
* @{
*/
/**
* os cputime usecs to ticks
*
* Converts the given number of microseconds into cputime ticks.
*
* @param usecs The number of microseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'usecs'
*/
uint32_t
os_cputime_usecs_to_ticks(uint32_t usecs)
{
uint64_t ticks;
/*
* Faster calculation but could be off 1 full tick since we do not
* add residual back. Adding back the residual is commented out below, but
* shown.
*/
ticks = (1ULL << 32) * MYNEWT_VAL(OS_CPUTIME_FREQ) / 1000000 * usecs;
/* Residual for 32768 Hz. */
//ticks += ((uint64_t)usecs * (1526122139+1)) >> 32;
return ticks >> 32;
}
/**
* cputime ticks to usecs
*
* Convert the given number of ticks into microseconds.
*
* @param ticks The number of ticks to convert to microseconds.
*
* @return uint32_t The number of microseconds corresponding to 'ticks'
*
* NOTE: This calculation will overflow if the value for ticks is greater
* than 140737488. I am not going to check that here because that many ticks
* is about 4222 seconds, way more than what this routine should be used for.
*/
uint32_t
os_cputime_ticks_to_usecs(uint32_t ticks)
{
uint32_t usecs;
uint32_t shift;
uint32_t freq;
/* Given: `freq = 2^n`, calculate `n`. */
/* Note: this looks like a lot of work, but gcc can optimize it away since
* `freq` is known at compile time.
*/
freq = MYNEWT_VAL(OS_CPUTIME_FREQ);
shift = 0;
while (freq != 0) {
freq >>= 1;
shift++;
}
if (shift <= 7) {
return 0;
}
shift -= 7;
usecs = ((ticks >> shift) * 15625) + (((ticks & 0x1ff) * 15625) >> shift);
return usecs;
}
/**
* @} OSCPUTime
* @} OSKernel
*/
#endif
+346
View File
@@ -0,0 +1,346 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/os.h"
#include "os/queue.h"
#include "os/os_dev.h"
#include <string.h>
/**
* @addtogroup OSKernel
* @{
* @defgroup OSDevice Device Framework
* @{
*/
static STAILQ_HEAD(, os_dev) g_os_dev_list;
static int
os_dev_init(struct os_dev *dev, char *name, uint8_t stage,
uint8_t priority, os_dev_init_func_t od_init, void *arg)
{
dev->od_name = name;
dev->od_stage = stage;
dev->od_priority = priority;
/* assume these are set after the fact. */
dev->od_flags = 0;
dev->od_open_ref = 0;
dev->od_init = od_init;
dev->od_init_arg = arg;
memset(&dev->od_handlers, 0, sizeof(dev->od_handlers));
return (0);
}
/**
* Add the device to the device tree. This is a private function.
*
* @param dev The device to add to the device tree.
*
* @return 0 on success, non-zero on failure.
*/
static int
os_dev_add(struct os_dev *dev)
{
struct os_dev *cur_dev;
/* If no devices present, insert into head */
if (STAILQ_FIRST(&g_os_dev_list) == NULL) {
STAILQ_INSERT_HEAD(&g_os_dev_list, dev, od_next);
return (0);
}
/* Add devices to the list, sorted first by stage, then by
* priority. Keep sorted in this order for initialization
* stage.
*/
cur_dev = NULL;
STAILQ_FOREACH(cur_dev, &g_os_dev_list, od_next) {
if (cur_dev->od_stage > dev->od_stage) {
continue;
}
if (dev->od_priority >= cur_dev->od_priority) {
break;
}
}
if (cur_dev) {
STAILQ_INSERT_AFTER(&g_os_dev_list, cur_dev, dev, od_next);
} else {
STAILQ_INSERT_TAIL(&g_os_dev_list, dev, od_next);
}
return (0);
}
/**
* Call device initialize routine, and mark it ready. This is a private
* function.
*
* @param dev The device to initialize.
*
* @return 0 on success, non-zero on failure.
*/
static int
os_dev_initialize(struct os_dev *dev)
{
int rc;
rc = dev->od_init(dev, dev->od_init_arg);
if (rc != 0) {
if (dev->od_flags & OS_DEV_F_INIT_CRITICAL) {
goto err;
}
} else {
dev->od_flags |= OS_DEV_F_STATUS_READY;
}
return 0;
err:
return rc;
}
/**
* Create a new device in the kernel.
*
* @param dev The device to create.
* @param name The name of the device to create.
* @param stage The stage to initialize that device to.
* @param priority The priority of initializing that device
* @param od_init The initialization function to call for this
* device.
* @param arg The argument to provide this device initialization
* function.
*
* @return 0 on success, non-zero on failure.
*/
int
os_dev_create(struct os_dev *dev, char *name, uint8_t stage,
uint8_t priority, os_dev_init_func_t od_init, void *arg)
{
int rc;
rc = os_dev_init(dev, name, stage, priority, od_init, arg);
if (rc != 0) {
goto err;
}
rc = os_dev_add(dev);
if (rc != 0) {
goto err;
}
if (g_os_started) {
rc = os_dev_initialize(dev);
}
err:
return (rc);
}
/**
* Initialize all devices for a given state.
*
* @param stage The stage to initialize.
*
* @return 0 on success, non-zero on failure.
*/
int
os_dev_initialize_all(uint8_t stage)
{
struct os_dev *dev;
int rc = 0;
STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
if (dev->od_stage == stage) {
rc = os_dev_initialize(dev);
if (rc) {
break;
}
}
}
return (rc);
}
/**
* Suspend all devices.
*
* @param dev The device to suspend
* @param suspend_t The number of ticks to suspend this device for
* @param force Whether or not to force suspending the device
*
* @return 0 on success, or a non-zero error code if one of the devices
* returned it.
*/
int
os_dev_suspend_all(os_time_t suspend_t, uint8_t force)
{
struct os_dev *dev;
int suspend_failure;
int rc;
suspend_failure = 0;
STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
rc = os_dev_suspend(dev, suspend_t, force);
if (rc != 0) {
suspend_failure = OS_ERROR;
}
}
return (suspend_failure);
}
/**
* Resume all the devices that were suspended.
*
* @return 0 on success, -1 if any of the devices have failed to resume.
*/
int
os_dev_resume_all(void)
{
struct os_dev *dev;
int rc;
STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
rc = os_dev_resume(dev);
if (rc != 0) {
goto err;
}
}
return (0);
err:
return (rc);
}
/**
* Lookup a device by name.
*
* WARNING: This should be called before any locking on the device is done, or
* the device list itself is modified in any context. There is no locking.
*
* @param name The name of the device to look up.
*
* @return A pointer to the device corresponding to name, or NULL if not found.
*/
struct os_dev *
os_dev_lookup(char *name)
{
struct os_dev *dev;
dev = NULL;
STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
if (!strcmp(dev->od_name, name)) {
break;
}
}
return (dev);
}
/**
* Open a device.
*
* @param dev The device to open
* @param timo The timeout to open the device, if not specified.
* @param arg The argument to the device open() call.
*
* @return 0 on success, non-zero on failure.
*/
struct os_dev *
os_dev_open(char *devname, uint32_t timo, void *arg)
{
struct os_dev *dev;
os_sr_t sr;
int rc;
dev = os_dev_lookup(devname);
if (dev == NULL) {
return (NULL);
}
/* Device is not ready to be opened. */
if ((dev->od_flags & OS_DEV_F_STATUS_READY) == 0) {
return (NULL);
}
if (dev->od_handlers.od_open) {
rc = dev->od_handlers.od_open(dev, timo, arg);
if (rc != 0) {
goto err;
}
}
OS_ENTER_CRITICAL(sr);
++dev->od_open_ref;
dev->od_flags |= OS_DEV_F_STATUS_OPEN;
OS_EXIT_CRITICAL(sr);
return (dev);
err:
return (NULL);
}
/**
* Close a device.
*
* @param dev The device to close
*
* @return 0 on success, non-zero on failure.
*/
int
os_dev_close(struct os_dev *dev)
{
int rc;
os_sr_t sr;
if (dev->od_handlers.od_close) {
rc = dev->od_handlers.od_close(dev);
if (rc != 0) {
goto err;
}
}
OS_ENTER_CRITICAL(sr);
if (--dev->od_open_ref == 0) {
dev->od_flags &= ~OS_DEV_F_STATUS_OPEN;
}
OS_EXIT_CRITICAL(sr);
return (0);
err:
return (rc);
}
/**
* Clears the device list. This function does not close any devices or free
* any resources; its purpose is to allow a full system reset between unit
* tests.
*/
void
os_dev_reset(void)
{
STAILQ_INIT(&g_os_dev_list);
}
/**
* @} OSDevice
* @} OSKernel
*/
+354
View File
@@ -0,0 +1,354 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <assert.h>
#include <string.h>
#include "os/os_trace_api.h"
#include "os/os.h"
/**
* @addtogroup OSKernel
* @{
* @defgroup OSEvent Event Queues
* @{
*/
static struct os_eventq os_eventq_main;
/**
* Initialize the event queue
*
* @param evq The event queue to initialize
*/
void
os_eventq_init(struct os_eventq *evq)
{
memset(evq, 0, sizeof(*evq));
STAILQ_INIT(&evq->evq_list);
}
int
os_eventq_inited(const struct os_eventq *evq)
{
return evq->evq_list.stqh_last != NULL;
}
/**
* Put an event on the event queue.
*
* @param evq The event queue to put an event on
* @param ev The event to put on the queue
*/
void
os_eventq_put(struct os_eventq *evq, struct os_event *ev)
{
int resched;
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
/* Do not queue if already queued */
if (OS_EVENT_QUEUED(ev)) {
OS_EXIT_CRITICAL(sr);
return;
}
os_trace_void(OS_TRACE_ID_EVQ_PUT);
/* Queue the event */
ev->ev_queued = 1;
STAILQ_INSERT_TAIL(&evq->evq_list, ev, ev_next);
resched = 0;
if (evq->evq_task) {
/* If task waiting on event, wake it up.
* Check if task is sleeping, because another event
* queue may have woken this task up beforehand.
*/
if (evq->evq_task->t_state == OS_TASK_SLEEP) {
os_sched_wakeup(evq->evq_task);
resched = 1;
}
/* Either way, NULL out the task, because the task will
* be awake upon exit of this function.
*/
evq->evq_task = NULL;
}
os_trace_end_call(OS_TRACE_ID_EVQ_PUT);
OS_EXIT_CRITICAL(sr);
if (resched) {
os_sched(NULL);
}
}
struct os_event *
os_eventq_get_no_wait(struct os_eventq *evq)
{
struct os_event *ev;
ev = STAILQ_FIRST(&evq->evq_list);
if (ev) {
STAILQ_REMOVE(&evq->evq_list, ev, os_event, ev_next);
ev->ev_queued = 0;
}
return ev;
}
/**
* Pull a single item from an event queue. This function blocks until there
* is an item on the event queue to read.
*
* @param evq The event queue to pull an event from
*
* @return The event from the queue
*/
struct os_event *
os_eventq_get(struct os_eventq *evq)
{
struct os_event *ev;
os_sr_t sr;
struct os_task *t;
t = os_sched_get_current_task();
if (evq->evq_owner != t) {
if (evq->evq_owner == NULL) {
evq->evq_owner = t;
} else {
/*
* A task is trying to read from event queue which is handled
* by another.
*/
assert(0);
}
}
OS_ENTER_CRITICAL(sr);
os_trace_void(OS_TRACE_ID_EVQ_GET);
pull_one:
ev = STAILQ_FIRST(&evq->evq_list);
if (ev) {
STAILQ_REMOVE(&evq->evq_list, ev, os_event, ev_next);
ev->ev_queued = 0;
t->t_flags &= ~OS_TASK_FLAG_EVQ_WAIT;
} else {
evq->evq_task = t;
os_sched_sleep(evq->evq_task, OS_TIMEOUT_NEVER);
t->t_flags |= OS_TASK_FLAG_EVQ_WAIT;
OS_EXIT_CRITICAL(sr);
os_sched(NULL);
OS_ENTER_CRITICAL(sr);
evq->evq_task = NULL;
goto pull_one;
}
os_trace_end_call(OS_TRACE_ID_EVQ_GET);
OS_EXIT_CRITICAL(sr);
return (ev);
}
void
os_eventq_run(struct os_eventq *evq)
{
struct os_event *ev;
ev = os_eventq_get(evq);
assert(ev->ev_cb != NULL);
ev->ev_cb(ev);
}
static struct os_event *
os_eventq_poll_0timo(struct os_eventq **evq, int nevqs)
{
struct os_event *ev;
os_sr_t sr;
int i;
ev = NULL;
OS_ENTER_CRITICAL(sr);
for (i = 0; i < nevqs; i++) {
ev = STAILQ_FIRST(&evq[i]->evq_list);
if (ev) {
STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
ev->ev_queued = 0;
break;
}
}
OS_EXIT_CRITICAL(sr);
return ev;
}
/**
* Poll the list of event queues specified by the evq parameter
* (size nevqs), and return the "first" event available on any of
* the queues. Event queues are searched in the order that they
* are passed in the array.
*
* @param evq Array of event queues
* @param nevqs Number of event queues in evq
* @param timo Timeout, forever if OS_WAIT_FOREVER is passed to poll.
*
* @return An event, or NULL if no events available
*/
struct os_event *
os_eventq_poll(struct os_eventq **evq, int nevqs, os_time_t timo)
{
struct os_event *ev;
struct os_task *cur_t;
int i, j;
os_sr_t sr;
/* If the timeout is 0, don't involve the scheduler at all. Grab an event
* if one is available, else return immediately.
*/
if (timo == 0) {
return os_eventq_poll_0timo(evq, nevqs);
}
ev = NULL;
OS_ENTER_CRITICAL(sr);
cur_t = os_sched_get_current_task();
for (i = 0; i < nevqs; i++) {
ev = STAILQ_FIRST(&evq[i]->evq_list);
if (ev) {
STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
ev->ev_queued = 0;
/* Reset the items that already have an evq task set. */
for (j = 0; j < i; j++) {
evq[j]->evq_task = NULL;
}
OS_EXIT_CRITICAL(sr);
goto has_event;
}
evq[i]->evq_task = cur_t;
}
cur_t->t_flags |= OS_TASK_FLAG_EVQ_WAIT;
os_sched_sleep(cur_t, timo);
OS_EXIT_CRITICAL(sr);
os_sched(NULL);
OS_ENTER_CRITICAL(sr);
cur_t->t_flags &= ~OS_TASK_FLAG_EVQ_WAIT;
for (i = 0; i < nevqs; i++) {
/* Go through the entire loop to clear the evq_task variable,
* given this task is no longer sleeping on the event queues.
* Return the first event found, so only grab the event if
* we haven't found one.
*/
if (!ev) {
ev = STAILQ_FIRST(&evq[i]->evq_list);
if (ev) {
STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
ev->ev_queued = 0;
}
}
evq[i]->evq_task = NULL;
}
OS_EXIT_CRITICAL(sr);
has_event:
return (ev);
}
/**
* Remove an event from the queue.
*
* @param evq The event queue to remove the event from
* @param ev The event to remove from the queue
*/
void
os_eventq_remove(struct os_eventq *evq, struct os_event *ev)
{
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
if (OS_EVENT_QUEUED(ev)) {
STAILQ_REMOVE(&evq->evq_list, ev, os_event, ev_next);
}
ev->ev_queued = 0;
OS_EXIT_CRITICAL(sr);
}
/**
* Retrieves the default event queue processed by OS main task.
*
* @return The default event queue.
*/
struct os_eventq *
os_eventq_dflt_get(void)
{
return &os_eventq_main;
}
/**
* [DEPRECATED - packages should manually enqueue start events to the default
* task instead of calling this function]
*
* Reassigns an event queue pointer to the specified value. This function is
* used for configuring a package to use a particular event queue. A package's
* event queue can generally be reassigned repeatedly. If the package has a
* startup event, the event is moved from the current queue (if any) to the
* specified queue.
*
* @param cur_evq Points to the eventq pointer to reassign.
* *cur_evq should be NULL if the package's
* eventq has not been assigned yet.
* @param new_evq The eventq that the package should be
* associated with.
* @param start_ev The package's startup event, if any. If this
* is non-NULL, the event gets removed from
* the current queue (if set), and enqueued to
* the new eventq.
*/
void
os_eventq_designate(struct os_eventq **cur_evq,
struct os_eventq *new_evq,
struct os_event *start_ev)
{
struct os_eventq *prev_evq;
prev_evq = *cur_evq;
*cur_evq = new_evq;
if (start_ev != NULL) {
if (start_ev->ev_queued) {
assert(prev_evq != NULL);
os_eventq_remove(prev_evq, start_ev);
}
os_eventq_put(new_evq, start_ev);
}
}
/**
* @} OSEvent
* @} OSKernel
*/
+124
View File
@@ -0,0 +1,124 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "syscfg/syscfg.h"
#include <assert.h>
#include "os/os_mutex.h"
#include "os/os_heap.h"
/**
* @addtogroup OSKernel
* @{
* @defgroup OSGeneral
* @{
*/
#if MYNEWT_VAL(OS_SCHEDULING)
static struct os_mutex os_malloc_mutex;
#endif
static void
os_malloc_lock(void)
{
#if MYNEWT_VAL(OS_SCHEDULING)
int rc;
if (g_os_started) {
rc = os_mutex_pend(&os_malloc_mutex, 0xffffffff);
assert(rc == 0);
}
#endif
}
static void
os_malloc_unlock(void)
{
#if MYNEWT_VAL(OS_SCHEDULING)
int rc;
if (g_os_started) {
rc = os_mutex_release(&os_malloc_mutex);
assert(rc == 0);
}
#endif
}
/**
* Operating system level malloc(). This ensures that a safe malloc occurs
* within the context of the OS. Depending on platform, the OS may rely on
* libc's malloc() implementation, which is not guaranteed to be thread-safe.
* This malloc() will always be thread-safe.
*
* @param size The number of bytes to allocate
*
* @return A pointer to the memory region allocated.
*/
void *
os_malloc(size_t size)
{
void *ptr;
os_malloc_lock();
ptr = malloc(size);
os_malloc_unlock();
return ptr;
}
/**
* Operating system level free(). See description of os_malloc() for reasoning.
*
* Free's memory allocated by malloc.
*
* @param mem The memory to free.
*/
void
os_free(void *mem)
{
os_malloc_lock();
free(mem);
os_malloc_unlock();
}
/**
* Operating system level realloc(). See description of os_malloc() for reasoning.
*
* Reallocates the memory at ptr, to be size contiguouos bytes.
*
* @param ptr A pointer to the memory to allocate
* @param size The number of contiguouos bytes to allocate at that location
*
* @return A pointer to memory of size, or NULL on failure to allocate
*/
void *
os_realloc(void *ptr, size_t size)
{
void *new_ptr;
os_malloc_lock();
new_ptr = realloc(ptr, size);
os_malloc_unlock();
return new_ptr;
}
/**
* @} OSGeneral
* @} OS Kernel
*/
File diff suppressed because it is too large Load Diff
+321
View File
@@ -0,0 +1,321 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/os.h"
#include <string.h>
#include <assert.h>
#include <stdbool.h>
/**
* @addtogroup OSKernel
* @{
* @defgroup OSMempool Memory Pools
* @{
*/
#define OS_MEM_TRUE_BLOCK_SIZE(bsize) OS_ALIGN(bsize, OS_ALIGNMENT)
#define OS_MEMPOOL_TRUE_BLOCK_SIZE(mp) OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size)
STAILQ_HEAD(, os_mempool) g_os_mempool_list =
STAILQ_HEAD_INITIALIZER(g_os_mempool_list);
#if MYNEWT_VAL(OS_MEMPOOL_POISON)
static uint32_t os_mem_poison = 0xde7ec7ed;
static void
os_mempool_poison(void *start, int sz)
{
int i;
char *p = start;
for (i = sizeof(struct os_memblock); i < sz;
i = i + sizeof(os_mem_poison)) {
memcpy(p + i, &os_mem_poison, min(sizeof(os_mem_poison), sz - i));
}
}
static void
os_mempool_poison_check(void *start, int sz)
{
int i;
char *p = start;
for (i = sizeof(struct os_memblock); i < sz;
i = i + sizeof(os_mem_poison)) {
assert(!memcmp(p + i, &os_mem_poison,
min(sizeof(os_mem_poison), sz - i)));
}
}
#else
#define os_mempool_poison(start, sz)
#define os_mempool_poison_check(start, sz)
#endif
/**
* os mempool init
*
* Initialize a memory pool.
*
* @param mp Pointer to a pointer to a mempool
* @param blocks The number of blocks in the pool
* @param blocks_size The size of the block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
*
* @return os_error_t
*/
os_error_t
os_mempool_init(struct os_mempool *mp, int blocks, int block_size,
void *membuf, char *name)
{
int true_block_size;
uint8_t *block_addr;
struct os_memblock *block_ptr;
/* Check for valid parameters */
if (!mp || (blocks < 0) || (block_size <= sizeof(struct os_memblock))) {
return OS_INVALID_PARM;
}
if ((!membuf) && (blocks != 0)) {
return OS_INVALID_PARM;
}
if (membuf != NULL) {
/* Blocks need to be sized properly and memory buffer should be
* aligned
*/
if (((uint32_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
return OS_MEM_NOT_ALIGNED;
}
}
true_block_size = OS_MEM_TRUE_BLOCK_SIZE(block_size);
/* Initialize the memory pool structure */
mp->mp_block_size = block_size;
mp->mp_num_free = blocks;
mp->mp_min_free = blocks;
mp->mp_num_blocks = blocks;
mp->mp_membuf_addr = (uint32_t)membuf;
mp->name = name;
os_mempool_poison(membuf, true_block_size);
SLIST_FIRST(mp) = membuf;
/* Chain the memory blocks to the free list */
block_addr = (uint8_t *)membuf;
block_ptr = (struct os_memblock *)block_addr;
while (blocks > 1) {
block_addr += true_block_size;
os_mempool_poison(block_addr, true_block_size);
SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
block_ptr = (struct os_memblock *)block_addr;
--blocks;
}
/* Last one in the list should be NULL */
SLIST_NEXT(block_ptr, mb_next) = NULL;
STAILQ_INSERT_TAIL(&g_os_mempool_list, mp, mp_list);
return OS_OK;
}
/**
* Performs an integrity check of the specified mempool. This function
* attempts to detect memory corruption in the specified memory pool.
*
* @param mp The mempool to check.
*
* @return true if the memory pool passes the integrity
* check;
* false if the memory pool is corrupt.
*/
bool
os_mempool_is_sane(const struct os_mempool *mp)
{
struct os_memblock *block;
/* Verify that each block in the free list belongs to the mempool. */
SLIST_FOREACH(block, mp, mb_next) {
if (!os_memblock_from(mp, block)) {
return false;
}
os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
}
return true;
}
/**
* Checks if a memory block was allocated from the specified mempool.
*
* @param mp The mempool to check as parent.
* @param block_addr The memory block to check as child.
*
* @return 0 if the block does not belong to the mempool;
* 1 if the block does belong to the mempool.
*/
int
os_memblock_from(const struct os_mempool *mp, const void *block_addr)
{
uint32_t true_block_size;
uint32_t baddr32;
uint32_t end;
_Static_assert(sizeof block_addr == sizeof baddr32,
"Pointer to void must be 32-bits.");
baddr32 = (uint32_t)block_addr;
true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
/* Check that the block is in the memory buffer range. */
if ((baddr32 < mp->mp_membuf_addr) || (baddr32 >= end)) {
return 0;
}
/* All freed blocks should be on true block size boundaries! */
if (((baddr32 - mp->mp_membuf_addr) % true_block_size) != 0) {
return 0;
}
return 1;
}
/**
* os memblock get
*
* Get a memory block from a memory pool
*
* @param mp Pointer to the memory pool
*
* @return void* Pointer to block if available; NULL otherwise
*/
void *
os_memblock_get(struct os_mempool *mp)
{
os_sr_t sr;
struct os_memblock *block;
/* Check to make sure they passed in a memory pool (or something) */
block = NULL;
if (mp) {
OS_ENTER_CRITICAL(sr);
/* Check for any free */
if (mp->mp_num_free) {
/* Get a free block */
block = SLIST_FIRST(mp);
os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
/* Set new free list head */
SLIST_FIRST(mp) = SLIST_NEXT(block, mb_next);
/* Decrement number free by 1 */
mp->mp_num_free--;
if (mp->mp_min_free > mp->mp_num_free) {
mp->mp_min_free = mp->mp_num_free;
}
}
OS_EXIT_CRITICAL(sr);
}
return (void *)block;
}
/**
* os memblock put
*
* Puts the memory block back into the pool
*
* @param mp Pointer to memory pool
* @param block_addr Pointer to memory block
*
* @return os_error_t
*/
os_error_t
os_memblock_put(struct os_mempool *mp, void *block_addr)
{
os_sr_t sr;
struct os_memblock *block;
/* Make sure parameters are valid */
if ((mp == NULL) || (block_addr == NULL)) {
return OS_INVALID_PARM;
}
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
/* Check that the block we are freeing is a valid block! */
assert(os_memblock_from(mp, block_addr));
/*
* Check for duplicate free.
*/
SLIST_FOREACH(block, mp, mb_next) {
assert(block != (struct os_memblock *)block_addr);
}
#endif
os_mempool_poison(block_addr, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
block = (struct os_memblock *)block_addr;
OS_ENTER_CRITICAL(sr);
/* Chain current free list pointer to this block; make this block head */
SLIST_NEXT(block, mb_next) = SLIST_FIRST(mp);
SLIST_FIRST(mp) = block;
/* XXX: Should we check that the number free <= number blocks? */
/* Increment number free */
mp->mp_num_free++;
OS_EXIT_CRITICAL(sr);
return OS_OK;
}
struct os_mempool *
os_mempool_info_get_next(struct os_mempool *mp, struct os_mempool_info *omi)
{
struct os_mempool *cur;
if (mp == NULL) {
cur = STAILQ_FIRST(&g_os_mempool_list);
} else {
cur = STAILQ_NEXT(mp, mp_list);
}
if (cur == NULL) {
return (NULL);
}
omi->omi_block_size = cur->mp_block_size;
omi->omi_num_blocks = cur->mp_num_blocks;
omi->omi_num_free = cur->mp_num_free;
omi->omi_min_free = cur->mp_min_free;
strncpy(omi->omi_name, cur->name, sizeof(omi->omi_name));
return (cur);
}
/**
* @} OSMempool
* @} OSKernel
*/
+88
View File
@@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <assert.h>
#include "../os/os_priv.h"
#include "sysinit/sysinit.h"
#include "syscfg/syscfg.h"
#include "os/os_mempool.h"
#include "mem/mem.h"
#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
#define SYSINIT_MSYS_1_MEMBLOCK_SIZE \
OS_ALIGN(MYNEWT_VAL(MSYS_1_BLOCK_SIZE), 4)
#define SYSINIT_MSYS_1_MEMPOOL_SIZE \
OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_1_BLOCK_COUNT), \
SYSINIT_MSYS_1_MEMBLOCK_SIZE)
static os_membuf_t os_msys_init_1_data[SYSINIT_MSYS_1_MEMPOOL_SIZE];
static struct os_mbuf_pool os_msys_init_1_mbuf_pool;
static struct os_mempool os_msys_init_1_mempool;
#endif
#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
#define SYSINIT_MSYS_2_MEMBLOCK_SIZE \
OS_ALIGN(MYNEWT_VAL(MSYS_2_BLOCK_SIZE), 4)
#define SYSINIT_MSYS_2_MEMPOOL_SIZE \
OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_2_BLOCK_COUNT), \
SYSINIT_MSYS_2_MEMBLOCK_SIZE)
static os_membuf_t os_msys_init_2_data[SYSINIT_MSYS_2_MEMPOOL_SIZE];
static struct os_mbuf_pool os_msys_init_2_mbuf_pool;
static struct os_mempool os_msys_init_2_mempool;
#endif
static void
os_msys_init_once(void *data, struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool,
int block_count, int block_size, char *name)
{
int rc;
rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size,
name);
SYSINIT_PANIC_ASSERT(rc == 0);
rc = os_msys_register(mbuf_pool);
SYSINIT_PANIC_ASSERT(rc == 0);
}
void
os_msys_init(void)
{
os_msys_reset();
(void)os_msys_init_once;
#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
os_msys_init_once(os_msys_init_1_data,
&os_msys_init_1_mempool,
&os_msys_init_1_mbuf_pool,
MYNEWT_VAL(MSYS_1_BLOCK_COUNT),
SYSINIT_MSYS_1_MEMBLOCK_SIZE,
"msys_1");
#endif
#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
os_msys_init_once(os_msys_init_2_data,
&os_msys_init_2_mempool,
&os_msys_init_2_mbuf_pool,
MYNEWT_VAL(MSYS_2_BLOCK_COUNT),
SYSINIT_MSYS_2_MEMBLOCK_SIZE,
"msys_2");
#endif
}
+262
View File
@@ -0,0 +1,262 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/os.h"
#include "os/os_trace_api.h"
#include <assert.h>
/**
* @addtogroup OSKernel
* @{
* @defgroup OSMutex Mutexes
* @{
*/
/**
* os mutex create
*
* Create a mutex and initialize it.
*
* @param mu Pointer to mutex
*
* @return os_error_t
* OS_INVALID_PARM Mutex passed in was NULL.
* OS_OK no error.
*/
os_error_t
os_mutex_init(struct os_mutex *mu)
{
if (!mu) {
return OS_INVALID_PARM;
}
os_trace_void(OS_TRACE_ID_MUTEX_INIT);
/* Initialize to 0 */
mu->mu_prio = 0;
mu->mu_level = 0;
mu->mu_owner = NULL;
SLIST_FIRST(&mu->mu_head) = NULL;
os_trace_end_call(OS_TRACE_ID_MUTEX_INIT);
return OS_OK;
}
/**
* os mutex release
*
* Release a mutex.
*
* @param mu Pointer to the mutex to be released
*
* @return os_error_t
* OS_INVALID_PARM Mutex passed in was NULL.
* OS_BAD_MUTEX Mutex was not granted to current task (not owner).
* OS_OK No error
*/
os_error_t
os_mutex_release(struct os_mutex *mu)
{
int resched;
os_sr_t sr;
struct os_task *current;
struct os_task *rdy;
/* Check if OS is started */
if (!g_os_started) {
return (OS_NOT_STARTED);
}
/* Check for valid mutex */
if (!mu) {
return OS_INVALID_PARM;
}
/* We better own this mutex! */
current = os_sched_get_current_task();
if ((mu->mu_level == 0) || (mu->mu_owner != current)) {
return (OS_BAD_MUTEX);
}
/* Decrement nesting level by 1. If not zero, nested (so dont release!) */
--mu->mu_level;
if (mu->mu_level != 0) {
return (OS_OK);
}
OS_ENTER_CRITICAL(sr);
os_trace_void(OS_TRACE_ID_MUTEX_RELEASE);
/* Restore owner task's priority; resort list if different */
if (current->t_prio != mu->mu_prio) {
current->t_prio = mu->mu_prio;
os_sched_resort(current);
}
/* Check if tasks are waiting for the mutex */
rdy = SLIST_FIRST(&mu->mu_head);
if (rdy) {
/* There is one waiting. Wake it up */
assert(rdy->t_obj);
os_sched_wakeup(rdy);
/* Set mutex internals */
mu->mu_level = 1;
mu->mu_prio = rdy->t_prio;
}
/* Set new owner of mutex (or NULL if not owned) */
mu->mu_owner = rdy;
if (rdy) {
rdy->t_lockcnt++;
}
--current->t_lockcnt;
/* Do we need to re-schedule? */
resched = 0;
rdy = os_sched_next_task();
if (rdy != current) {
resched = 1;
}
OS_EXIT_CRITICAL(sr);
/* Re-schedule if needed */
if (resched) {
os_sched(rdy);
}
os_trace_end_call(OS_TRACE_ID_MUTEX_RELEASE);
return OS_OK;
}
/**
* os mutex pend
*
* Pend (wait) for a mutex.
*
* @param mu Pointer to mutex.
* @param timeout Timeout, in os ticks. A timeout of 0 means do
* not wait if not available. A timeout of
* 0xFFFFFFFF means wait forever.
*
*
* @return os_error_t
* OS_INVALID_PARM Mutex passed in was NULL.
* OS_TIMEOUT Mutex was owned by another task and timeout=0
* OS_OK no error.
*/
os_error_t
os_mutex_pend(struct os_mutex *mu, uint32_t timeout)
{
os_sr_t sr;
os_error_t rc;
struct os_task *current;
struct os_task *entry;
struct os_task *last;
/* OS must be started when calling this function */
if (!g_os_started) {
return (OS_NOT_STARTED);
}
/* Check for valid mutex */
if (!mu) {
return OS_INVALID_PARM;
}
OS_ENTER_CRITICAL(sr);
/* Is this owned? */
current = os_sched_get_current_task();
if (mu->mu_level == 0) {
mu->mu_owner = current;
mu->mu_prio = current->t_prio;
current->t_lockcnt++;
mu->mu_level = 1;
OS_EXIT_CRITICAL(sr);
return OS_OK;
}
/* Are we owner? */
if (mu->mu_owner == current) {
++mu->mu_level;
OS_EXIT_CRITICAL(sr);
return OS_OK;
}
/* Mutex is not owned by us. If timeout is 0, return immediately */
if (timeout == 0) {
OS_EXIT_CRITICAL(sr);
return OS_TIMEOUT;
}
os_trace_void(OS_TRACE_ID_MUTEX_PEND);
/* Change priority of owner if needed */
if (mu->mu_owner->t_prio > current->t_prio) {
mu->mu_owner->t_prio = current->t_prio;
os_sched_resort(mu->mu_owner);
}
/* Link current task to tasks waiting for mutex */
last = NULL;
if (!SLIST_EMPTY(&mu->mu_head)) {
/* Insert in priority order */
SLIST_FOREACH(entry, &mu->mu_head, t_obj_list) {
if (current->t_prio < entry->t_prio) {
break;
}
last = entry;
}
}
if (last) {
SLIST_INSERT_AFTER(last, current, t_obj_list);
} else {
SLIST_INSERT_HEAD(&mu->mu_head, current, t_obj_list);
}
/* Set mutex pointer in task */
current->t_obj = mu;
current->t_flags |= OS_TASK_FLAG_MUTEX_WAIT;
os_sched_sleep(current, timeout);
OS_EXIT_CRITICAL(sr);
os_sched(NULL);
OS_ENTER_CRITICAL(sr);
current->t_flags &= ~OS_TASK_FLAG_MUTEX_WAIT;
OS_EXIT_CRITICAL(sr);
/* If we are owner we did not time out. */
if (mu->mu_owner == current) {
rc = OS_OK;
} else {
rc = OS_TIMEOUT;
}
os_trace_end_call(OS_TRACE_ID_MUTEX_PEND);
return rc;
}
/**
* @} OSMutex
* @} OSKernel
*/
+41
View File
@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_OS_PRIV_
#define H_OS_PRIV_
#include "os/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
extern struct os_task g_idle_task;
extern struct os_task_list g_os_run_list;
extern struct os_task_list g_os_sleep_list;
extern struct os_task_stailq g_os_task_list;
extern struct os_callout_list g_callout_list;
void os_msys_init(void);
#ifdef __cplusplus
}
#endif
#endif
+250
View File
@@ -0,0 +1,250 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <assert.h>
#include <string.h>
#include "os/os.h"
/**
* @addtogroup OSKernel
* @{
* @defgroup OSSanity Sanity
* @{
*/
SLIST_HEAD(, os_sanity_check) g_os_sanity_check_list =
SLIST_HEAD_INITIALIZER(os_sanity_check_list);
struct os_mutex g_os_sanity_check_mu;
/**
* Initialize a sanity check
*
* @param sc The sanity check to initialize
*
* @return 0 on success, error code on failure.
*/
int
os_sanity_check_init(struct os_sanity_check *sc)
{
memset(sc, 0, sizeof(*sc));
return (0);
}
/**
* Lock the sanity check list
*
* @return 0 on success, error code on failure.
*/
static int
os_sanity_check_list_lock(void)
{
int rc;
if (!g_os_started) {
return (0);
}
rc = os_mutex_pend(&g_os_sanity_check_mu, OS_WAIT_FOREVER);
if (rc != OS_OK) {
goto err;
}
return (0);
err:
return (rc);
}
/**
* Unlock the sanity check list
*
* @return 0 on success, error code on failure
*/
static int
os_sanity_check_list_unlock(void)
{
int rc;
if (!g_os_started) {
return (0);
}
rc = os_mutex_release(&g_os_sanity_check_mu);
if (rc != 0) {
goto err;
}
return (0);
err:
return (rc);
}
/**
* Provide a "task checkin" for the sanity task.
*
* @param t The task to check in
*
* @return 0 on success, error code on failure
*/
int
os_sanity_task_checkin(struct os_task *t)
{
int rc;
if (t == NULL) {
t = os_sched_get_current_task();
}
rc = os_sanity_check_reset(&t->t_sanity_check);
if (rc != OS_OK) {
goto err;
}
return (0);
err:
return (rc);
}
/**
* Register a sanity check
*
* @param sc The sanity check to register
*
* @return 0 on success, error code on failure
*/
int
os_sanity_check_register(struct os_sanity_check *sc)
{
int rc;
rc = os_sanity_check_list_lock();
if (rc != OS_OK) {
goto err;
}
SLIST_INSERT_HEAD(&g_os_sanity_check_list, sc, sc_next);
rc = os_sanity_check_list_unlock();
if (rc != OS_OK) {
goto err;
}
return (0);
err:
return (rc);
}
/**
* Reset the os sanity check, so that it doesn't trip up the
* sanity timer.
*
* @param sc The sanity check to reset
*
* @return 0 on success, error code on failure
*/
int
os_sanity_check_reset(struct os_sanity_check *sc)
{
int rc;
rc = os_sanity_check_list_lock();
if (rc != OS_OK) {
goto err;
}
sc->sc_checkin_last = os_time_get();
rc = os_sanity_check_list_unlock();
if (rc != OS_OK) {
goto err;
}
return (0);
err:
return (rc);
}
/*
* Called from the IDLE task context, every MYNEWT_VAL(SANITY_INTERVAL) msecs.
*
* Goes through the sanity check list, and performs sanity checks. If any of
* these checks failed, or tasks have not checked in, it resets the processor.
*/
void
os_sanity_run(void)
{
struct os_sanity_check *sc;
int rc;
rc = os_sanity_check_list_lock();
if (rc != 0) {
assert(0);
}
SLIST_FOREACH(sc, &g_os_sanity_check_list, sc_next) {
rc = OS_OK;
if (sc->sc_func) {
rc = sc->sc_func(sc, sc->sc_arg);
if (rc == OS_OK) {
sc->sc_checkin_last = os_time_get();
continue;
}
}
if (OS_TIME_TICK_GT(os_time_get(),
sc->sc_checkin_last + sc->sc_checkin_itvl)) {
assert(0);
}
}
rc = os_sanity_check_list_unlock();
if (rc != 0) {
assert(0);
}
}
/**
* Initialize the sanity task and mutex.
*
* @return 0 on success, error code on failure
*/
int
os_sanity_init(void)
{
int rc;
rc = os_mutex_init(&g_os_sanity_check_mu);
if (rc != 0) {
goto err;
}
return (0);
err:
return (rc);
}
/**
* @} OSSanity
* @} OSKernel
*/
+377
View File
@@ -0,0 +1,377 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/os.h"
#include "os/os_trace_api.h"
#include "os/queue.h"
#include <assert.h>
#include "../os/os_priv.h"
/**
* @addtogroup OSKernel
* @{
* @defgroup OSSched Scheduler
* @{
*/
struct os_task_list g_os_run_list = TAILQ_HEAD_INITIALIZER(g_os_run_list);
struct os_task_list g_os_sleep_list = TAILQ_HEAD_INITIALIZER(g_os_sleep_list);
struct os_task *g_current_task;
extern os_time_t g_os_time;
os_time_t g_os_last_ctx_sw_time;
/**
* os sched insert
*
* Insert a task into the scheduler list. This causes the task to be evaluated
* for running when os_sched is called.
*
* @param t Pointer to task to insert in run list
*
* @return int OS_OK: task was inserted into run list
* OS_EINVAL: Task was not in ready state.
*/
os_error_t
os_sched_insert(struct os_task *t)
{
struct os_task *entry;
os_sr_t sr;
os_error_t rc;
if (t->t_state != OS_TASK_READY) {
rc = OS_EINVAL;
goto err;
}
entry = NULL;
OS_ENTER_CRITICAL(sr);
TAILQ_FOREACH(entry, &g_os_run_list, t_os_list) {
if (t->t_prio < entry->t_prio) {
break;
}
}
if (entry) {
TAILQ_INSERT_BEFORE(entry, (struct os_task *) t, t_os_list);
} else {
TAILQ_INSERT_TAIL(&g_os_run_list, (struct os_task *) t, t_os_list);
}
OS_EXIT_CRITICAL(sr);
return (0);
err:
return (rc);
}
void
os_sched_ctx_sw_hook(struct os_task *next_t)
{
#if MYNEWT_VAL(OS_CTX_SW_STACK_CHECK)
os_stack_t *top;
int i;
top = g_current_task->t_stacktop - g_current_task->t_stacksize;
for (i = 0; i < MYNEWT_VAL(OS_CTX_SW_STACK_GUARD); i++) {
assert(top[i] == OS_STACK_PATTERN);
}
#endif
os_trace_task_start_exec(next_t->t_taskid);
next_t->t_ctx_sw_cnt++;
g_current_task->t_run_time += g_os_time - g_os_last_ctx_sw_time;
g_os_last_ctx_sw_time = g_os_time;
}
/**
* os sched get current task
*
* Returns the currently running task. Note that this task may or may not be
* the highest priority task ready to run.
*
*
* @return struct os_task*
*/
struct os_task *
os_sched_get_current_task(void)
{
return (g_current_task);
}
/**
* os sched set current task
*
* Sets the currently running task to 't'. Note that this function simply sets
* the global variable holding the currently running task. It does not perform
* a context switch or change the os run or sleep list.
*
* @param t Pointer to currently running task.
*/
void
os_sched_set_current_task(struct os_task *t)
{
g_current_task = t;
}
/**
* os sched
*
* Performs a context switch. When called, it will either find the highest
* priority task ready to run if next_t is NULL (i.e. the head of the os run
* list) or will schedule next_t as the task to run.
*
* @param next_t Task to run
*/
void
os_sched(struct os_task *next_t)
{
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
if (!next_t) {
next_t = os_sched_next_task();
}
os_arch_ctx_sw(next_t);
OS_EXIT_CRITICAL(sr);
}
/**
* os sched sleep
*
* Removes the task from the run list and puts it on the sleep list.
*
* @param t Task to put to sleep
* @param nticks Number of ticks to put task to sleep
*
* @return int
*
* NOTE: must be called with interrupts disabled! This function does not call
* the scheduler
*/
int
os_sched_sleep(struct os_task *t, os_time_t nticks)
{
struct os_task *entry;
entry = NULL;
TAILQ_REMOVE(&g_os_run_list, t, t_os_list);
t->t_state = OS_TASK_SLEEP;
t->t_next_wakeup = os_time_get() + nticks;
if (nticks == OS_TIMEOUT_NEVER) {
t->t_flags |= OS_TASK_FLAG_NO_TIMEOUT;
TAILQ_INSERT_TAIL(&g_os_sleep_list, t, t_os_list);
} else {
TAILQ_FOREACH(entry, &g_os_sleep_list, t_os_list) {
if ((entry->t_flags & OS_TASK_FLAG_NO_TIMEOUT) ||
OS_TIME_TICK_GT(entry->t_next_wakeup, t->t_next_wakeup)) {
break;
}
}
if (entry) {
TAILQ_INSERT_BEFORE(entry, t, t_os_list);
} else {
TAILQ_INSERT_TAIL(&g_os_sleep_list, t, t_os_list);
}
}
os_trace_task_stop_ready(t->t_taskid, OS_TASK_SLEEP);
return (0);
}
/**
* os sched remove
*
* XXX
* NOTE - This routine is currently experimental and not ready for common use
*
* Stops a task and removes it from the task list.
*
* @return int
*
* NOTE: must be called with interrupts disabled! This function does not call
* the scheduler
*/
int
os_sched_remove(struct os_task *t)
{
if (t->t_state == OS_TASK_SLEEP) {
TAILQ_REMOVE(&g_os_sleep_list, t, t_os_list);
} else if (t->t_state == OS_TASK_READY) {
TAILQ_REMOVE(&g_os_run_list, t, t_os_list);
}
t->t_next_wakeup = 0;
t->t_flags |= OS_TASK_FLAG_NO_TIMEOUT;
STAILQ_REMOVE(&g_os_task_list, t, os_task, t_os_task_list);
os_trace_task_stop_exec();
return OS_OK;
}
/**
* os sched wakeup
*
* Called to wake up a task. Waking up a task consists of setting the task state
* to READY and moving it from the sleep list to the run list.
*
* @param t Pointer to task to wake up.
*
* @return int
*
* NOTE: This function must be called with interrupts disabled.
*/
int
os_sched_wakeup(struct os_task *t)
{
struct os_task_obj *os_obj;
assert(t->t_state == OS_TASK_SLEEP);
/* Remove self from object list if waiting on one */
if (t->t_obj) {
os_obj = (struct os_task_obj *)t->t_obj;
assert(!SLIST_EMPTY(&os_obj->obj_head));
SLIST_REMOVE(&os_obj->obj_head, t, os_task, t_obj_list);
SLIST_NEXT(t, t_obj_list) = NULL;
t->t_obj = NULL;
}
/* Remove task from sleep list */
t->t_state = OS_TASK_READY;
t->t_next_wakeup = 0;
t->t_flags &= ~OS_TASK_FLAG_NO_TIMEOUT;
TAILQ_REMOVE(&g_os_sleep_list, t, t_os_list);
os_sched_insert(t);
return (0);
}
/**
* os sched os timer exp
*
* Called when the OS tick timer expires. Search the sleep list for any tasks
* that need waking up. This occurs when the current OS time exceeds the next
* wakeup time stored in the task. Any tasks that need waking up will be
* removed from the sleep list and added to the run list.
*
*/
void
os_sched_os_timer_exp(void)
{
struct os_task *t;
struct os_task *next;
os_time_t now;
os_sr_t sr;
now = os_time_get();
OS_ENTER_CRITICAL(sr);
/*
* Wakeup any tasks that have their sleep timer expired
*/
t = TAILQ_FIRST(&g_os_sleep_list);
while (t) {
/* If task waiting forever, do not check next wakeup time */
if (t->t_flags & OS_TASK_FLAG_NO_TIMEOUT) {
break;
}
next = TAILQ_NEXT(t, t_os_list);
if (OS_TIME_TICK_GEQ(now, t->t_next_wakeup)) {
os_trace_task_start_ready(t->t_taskid);
os_sched_wakeup(t);
} else {
break;
}
t = next;
}
OS_EXIT_CRITICAL(sr);
}
/*
* Return the number of ticks until the first sleep timer expires.If there are
* no such tasks then return OS_TIMEOUT_NEVER instead.
*/
os_time_t
os_sched_wakeup_ticks(os_time_t now)
{
os_time_t rt;
struct os_task *t;
OS_ASSERT_CRITICAL();
t = TAILQ_FIRST(&g_os_sleep_list);
if (t == NULL || (t->t_flags & OS_TASK_FLAG_NO_TIMEOUT)) {
rt = OS_TIMEOUT_NEVER;
} else if (OS_TIME_TICK_GEQ(t->t_next_wakeup, now)) {
rt = t->t_next_wakeup - now;
} else {
rt = 0; /* wakeup time was in the past */
}
return (rt);
}
/**
* os sched next task
*
* Returns the task that we should be running. This is the task at the head
* of the run list.
*
* NOTE: if you want to guarantee that the os run list does not change after
* calling this function you have to call it with interrupts disabled.
*
* @return struct os_task*
*/
struct os_task *
os_sched_next_task(void)
{
return (TAILQ_FIRST(&g_os_run_list));
}
/**
* os sched resort
*
* Resort a task that is in the ready list as its priority has
* changed. If the task is not in the ready state, there is
* nothing to do.
*
* @param t Pointer to task to insert back into ready to run
* list.
*
* NOTE: this function expects interrupts to be disabled so they
* are not disabled here.
*/
void
os_sched_resort(struct os_task *t)
{
if (t->t_state == OS_TASK_READY) {
TAILQ_REMOVE(&g_os_run_list, t, t_os_list);
os_sched_insert(t);
}
}
/**
* @} OSSched
* @} OSKernel
*/
+225
View File
@@ -0,0 +1,225 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/os.h"
#include <assert.h>
/**
* @addtogroup OSKernel
* @{
* @defgroup OSSem Semaphores
* @{
*/
/* XXX:
* 1) Should I check to see if we are within an ISR for some of these?
* 2) Would I do anything different for os_sem_release() if we were in an
* ISR when this was called?
*/
/**
* os sem initialize
*
* Initialize a semaphore
*
* @param sem Pointer to semaphore
* tokens: # of tokens the semaphore should contain initially.
*
* @return os_error_t
* OS_INVALID_PARM Semaphore passed in was NULL.
* OS_OK no error.
*/
os_error_t
os_sem_init(struct os_sem *sem, uint16_t tokens)
{
if (!sem) {
return OS_INVALID_PARM;
}
sem->sem_tokens = tokens;
SLIST_FIRST(&sem->sem_head) = NULL;
return OS_OK;
}
/**
* os sem release
*
* Release a semaphore.
*
* @param sem Pointer to the semaphore to be released
*
* @return os_error_t
* OS_INVALID_PARM Semaphore passed in was NULL.
* OS_OK No error
*/
os_error_t
os_sem_release(struct os_sem *sem)
{
int resched;
os_sr_t sr;
struct os_task *current;
struct os_task *rdy;
/* OS must be started to release semaphores */
if (!g_os_started) {
return (OS_NOT_STARTED);
}
/* Check for valid semaphore */
if (!sem) {
return OS_INVALID_PARM;
}
/* Get current task */
resched = 0;
current = os_sched_get_current_task();
OS_ENTER_CRITICAL(sr);
/* Check if tasks are waiting for the semaphore */
rdy = SLIST_FIRST(&sem->sem_head);
if (rdy) {
/* Clear flag that we are waiting on the semaphore; wake up task */
rdy->t_flags &= ~OS_TASK_FLAG_SEM_WAIT;
os_sched_wakeup(rdy);
/* Schedule if waiting task higher priority */
if (current->t_prio > rdy->t_prio) {
resched = 1;
}
} else {
/* Add to the number of tokens */
sem->sem_tokens++;
}
OS_EXIT_CRITICAL(sr);
/* Re-schedule if needed */
if (resched) {
os_sched(rdy);
}
return OS_OK;
}
/**
* os sem pend
*
* Pend (wait) for a semaphore.
*
* @param mu Pointer to semaphore.
* @param timeout Timeout, in os ticks. A timeout of 0 means do
* not wait if not available. A timeout of
* 0xFFFFFFFF means wait forever.
*
*
* @return os_error_t
* OS_INVALID_PARM Semaphore passed in was NULL.
* OS_TIMEOUT Semaphore was owned by another task and timeout=0
* OS_OK no error.
*/
os_error_t
os_sem_pend(struct os_sem *sem, uint32_t timeout)
{
os_sr_t sr;
os_error_t rc;
int sched;
struct os_task *current;
struct os_task *entry;
struct os_task *last;
/* Check if OS is started */
if (!g_os_started) {
return (OS_NOT_STARTED);
}
/* Check for valid semaphore */
if (!sem) {
return OS_INVALID_PARM;
}
/* Assume we dont have to put task to sleep; get current task */
sched = 0;
current = os_sched_get_current_task();
OS_ENTER_CRITICAL(sr);
/*
* If there is a token available, take it. If no token, either return
* with error if timeout was 0 or put this task to sleep.
*/
if (sem->sem_tokens != 0) {
sem->sem_tokens--;
rc = OS_OK;
} else if (timeout == 0) {
rc = OS_TIMEOUT;
} else {
/* Silence gcc maybe-uninitialized warning. */
rc = OS_OK;
/* Link current task to tasks waiting for semaphore */
current->t_obj = sem;
current->t_flags |= OS_TASK_FLAG_SEM_WAIT;
last = NULL;
if (!SLIST_EMPTY(&sem->sem_head)) {
/* Insert in priority order */
SLIST_FOREACH(entry, &sem->sem_head, t_obj_list) {
if (current->t_prio < entry->t_prio) {
break;
}
last = entry;
}
}
if (last) {
SLIST_INSERT_AFTER(last, current, t_obj_list);
} else {
SLIST_INSERT_HEAD(&sem->sem_head, current, t_obj_list);
}
/* We will put this task to sleep */
sched = 1;
os_sched_sleep(current, timeout);
}
OS_EXIT_CRITICAL(sr);
if (sched) {
os_sched(NULL);
/* Check if we timed out or got the semaphore */
if (current->t_flags & OS_TASK_FLAG_SEM_WAIT) {
OS_ENTER_CRITICAL(sr);
current->t_flags &= ~OS_TASK_FLAG_SEM_WAIT;
OS_EXIT_CRITICAL(sr);
rc = OS_TIMEOUT;
} else {
rc = OS_OK;
}
}
return rc;
}
/**
* @} OSSched
* @} OSKernel
*/
+284
View File
@@ -0,0 +1,284 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "os/os.h"
#include "os/os_trace_api.h"
#include <assert.h>
#include <string.h>
#include "../os/os_priv.h"
/**
* @addtogroup OSKernel
* @{
* @defgroup OSTask Tasks
* @{
*/
uint8_t g_task_id;
struct os_task_stailq g_os_task_list;
static void
_clear_stack(os_stack_t *stack_bottom, int size)
{
int i;
for (i = 0; i < size; i++) {
stack_bottom[i] = OS_STACK_PATTERN;
}
}
static inline uint8_t
os_task_next_id(void)
{
uint8_t rc;
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
rc = g_task_id;
g_task_id++;
OS_EXIT_CRITICAL(sr);
return (rc);
}
/**
* Return the number of tasks initialized.
*
* @return number of tasks initialized
*/
uint8_t
os_task_count(void)
{
return (g_task_id);
}
/**
* Initialize a task.
*
* This function initializes the task structure pointed to by t,
* clearing and setting it's stack pointer, provides sane defaults
* and sets the task as ready to run, and inserts it into the operating
* system scheduler.
*
* @param t The task to initialize
* @param name The name of the task to initialize
* @param func The task function to call
* @param arg The argument to pass to this task function
* @param prio The priority at which to run this task
* @param sanity_itvl The time at which this task should check in with the
* sanity task. OS_WAIT_FOREVER means never check in
* here.
* @param stack_bottom A pointer to the bottom of a task's stack
* @param stack_size The overall size of the task's stack.
*
* @return 0 on success, non-zero on failure.
*/
int
os_task_init(struct os_task *t, const char *name, os_task_func_t func,
void *arg, uint8_t prio, os_time_t sanity_itvl,
os_stack_t *stack_bottom, uint16_t stack_size)
{
struct os_sanity_check *sc;
int rc;
struct os_task *task;
memset(t, 0, sizeof(*t));
t->t_func = func;
t->t_arg = arg;
t->t_taskid = os_task_next_id();
t->t_prio = prio;
t->t_state = OS_TASK_READY;
t->t_name = name;
t->t_next_wakeup = 0;
rc = os_sanity_check_init(&t->t_sanity_check);
if (rc != OS_OK) {
goto err;
}
if (sanity_itvl != OS_WAIT_FOREVER) {
sc = (struct os_sanity_check *) &t->t_sanity_check;
sc->sc_checkin_itvl = sanity_itvl;
rc = os_sanity_check_register(sc);
if (rc != OS_OK) {
goto err;
}
}
_clear_stack(stack_bottom, stack_size);
t->t_stacktop = &stack_bottom[stack_size];
t->t_stacksize = stack_size;
t->t_stackptr = os_arch_task_stack_init(t, t->t_stacktop,
t->t_stacksize);
STAILQ_FOREACH(task, &g_os_task_list, t_os_task_list) {
assert(t->t_prio != task->t_prio);
}
/* insert this task into the task list */
STAILQ_INSERT_TAIL(&g_os_task_list, t, t_os_task_list);
/* insert this task into the scheduler list */
rc = os_sched_insert(t);
if (rc != OS_OK) {
goto err;
}
os_trace_task_info(t);
return (0);
err:
return (rc);
}
/*
* Removes specified task
* XXX
* NOTE: This interface is currently experimental and not ready for common use
*/
int
os_task_remove(struct os_task *t)
{
struct os_task *current;
int rc;
os_sr_t sr;
current = os_sched_get_current_task();
/*
* Can't suspend yourself
*/
if (t->t_taskid == current->t_taskid) {
return OS_INVALID_PARM;
}
/*
* If state is not READY or SLEEP, assume task has not been initialized
*/
if (t->t_state != OS_TASK_READY && t->t_state != OS_TASK_SLEEP)
{
return OS_NOT_STARTED;
}
/*
* Disallow suspending tasks which are waiting on a lock
*/
if (t->t_flags & (OS_TASK_FLAG_SEM_WAIT | OS_TASK_FLAG_MUTEX_WAIT |
OS_TASK_FLAG_EVQ_WAIT)) {
return OS_EBUSY;
}
/*
* Disallowing suspending tasks which are holding a mutex
*/
if (t->t_lockcnt) {
return OS_EBUSY;
}
OS_ENTER_CRITICAL(sr);
rc = os_sched_remove(t);
OS_EXIT_CRITICAL(sr);
return rc;
}
/**
* Iterate through tasks, and return the following information about them:
*
* - Priority
* - Task ID
* - State (ACTIVE, SLEEP)
* - Total Stack Usage
* - Stack Size
* - Context Switch Count
* - Runtime
* - Last & Next Sanity checkin
* - Task Name
*
* To get the first task in the list, call os_task_info_get_next() with a
* NULL pointer in the prev argument, and os_task_info_get_next() will
* return a pointer to the task structure, and fill out the os_task_info
* structure pointed to by oti.
*
* To get the next task in the list, provide the task structure returned
* by the previous call to os_task_info_get_next(), and os_task_info_get_next()
* will fill out the task structure pointed to by oti again, and return
* the next task in the list.
*
* @param prev The previous task returned by os_task_info_get_next(), or NULL
* to begin iteration.
* @param oti The OS task info structure to fill out.
*
* @return A pointer to the OS task that has been read, or NULL when finished
* iterating through all tasks.
*/
struct os_task *
os_task_info_get_next(const struct os_task *prev, struct os_task_info *oti)
{
struct os_task *next;
os_stack_t *top;
os_stack_t *bottom;
if (prev != NULL) {
next = STAILQ_NEXT(prev, t_os_task_list);
} else {
next = STAILQ_FIRST(&g_os_task_list);
}
if (next == NULL) {
return (NULL);
}
/* Otherwise, copy OS task information into the OTI structure, and
* return 1, which means continue
*/
oti->oti_prio = next->t_prio;
oti->oti_taskid = next->t_taskid;
oti->oti_state = next->t_state;
top = next->t_stacktop;
bottom = next->t_stacktop - next->t_stacksize;
while (bottom < top) {
if (*bottom != OS_STACK_PATTERN) {
break;
}
++bottom;
}
oti->oti_stkusage = (uint16_t) (next->t_stacktop - bottom);
oti->oti_stksize = next->t_stacksize;
oti->oti_cswcnt = next->t_ctx_sw_cnt;
oti->oti_runtime = next->t_run_time;
oti->oti_last_checkin = next->t_sanity_check.sc_checkin_last;
oti->oti_next_checkin = next->t_sanity_check.sc_checkin_last +
next->t_sanity_check.sc_checkin_itvl;
strncpy(oti->oti_name, next->t_name, sizeof(oti->oti_name));
return (next);
}
/**
* @} OSTask
* @} OSKernel
*/
+268
View File
@@ -0,0 +1,268 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "syscfg/syscfg.h"
#include <assert.h>
#include "os/os.h"
#include "os/queue.h"
/**
* @addtogroup OSKernel
* @{
* @defgroup OSTime Time
* @{
*/
CTASSERT(sizeof(os_time_t) == 4);
#define OS_USEC_PER_TICK (1000000 / OS_TICKS_PER_SEC)
os_time_t g_os_time;
/*
* Time-of-day collateral.
*/
static struct {
os_time_t ostime;
struct os_timeval uptime;
struct os_timeval utctime;
struct os_timezone timezone;
} basetod;
static void
os_deltatime(os_time_t delta, const struct os_timeval *base,
struct os_timeval *result)
{
struct os_timeval tvdelta;
tvdelta.tv_sec = delta / OS_TICKS_PER_SEC;
tvdelta.tv_usec = (delta % OS_TICKS_PER_SEC) * OS_USEC_PER_TICK;
os_timeradd(base, &tvdelta, result);
}
/**
* Get the current OS time in ticks
*
* @return OS time in ticks
*/
os_time_t
os_time_get(void)
{
return (g_os_time);
}
#if MYNEWT_VAL(OS_SCHEDULING)
static void
os_time_tick(int ticks)
{
os_sr_t sr;
os_time_t delta, prev_os_time;
assert(ticks >= 0);
OS_ENTER_CRITICAL(sr);
prev_os_time = g_os_time;
g_os_time += ticks;
/*
* Update 'basetod' when 'g_os_time' crosses the 0x00000000 and
* 0x80000000 thresholds.
*/
if ((prev_os_time ^ g_os_time) >> 31) {
delta = g_os_time - basetod.ostime;
os_deltatime(delta, &basetod.uptime, &basetod.uptime);
os_deltatime(delta, &basetod.utctime, &basetod.utctime);
basetod.ostime = g_os_time;
}
OS_EXIT_CRITICAL(sr);
}
/**
* Move OS time forward ticks.
*
* @param ticks The number of ticks to move time forward.
*/
void
os_time_advance(int ticks)
{
assert(ticks >= 0);
if (ticks > 0) {
if (!os_started()) {
g_os_time += ticks;
} else {
os_time_tick(ticks);
os_callout_tick();
os_sched_os_timer_exp();
os_sched(NULL);
}
}
}
#else
void
os_time_advance(int ticks)
{
g_os_time += ticks;
}
#endif
/**
* Puts the current task to sleep for the specified number of os ticks. There
* is no delay if ticks is <= 0.
*
* @param osticks Number of ticks to delay (<= 0 means no delay).
*/
void
os_time_delay(int32_t osticks)
{
os_sr_t sr;
if (osticks > 0) {
OS_ENTER_CRITICAL(sr);
os_sched_sleep(os_sched_get_current_task(), (os_time_t)osticks);
OS_EXIT_CRITICAL(sr);
os_sched(NULL);
}
}
/**
* Set the time of day. This does not modify os time, but rather just modifies
* the offset by which we are tracking real time against os time.
*
* @param utctime A timeval representing the UTC time we are setting
* @param tz The time-zone to apply against the utctime being set.
*
* @return 0 on success, non-zero on failure.
*/
int
os_settimeofday(struct os_timeval *utctime, struct os_timezone *tz)
{
os_sr_t sr;
os_time_t delta;
OS_ENTER_CRITICAL(sr);
if (utctime != NULL) {
/*
* Update all time-of-day base values.
*/
delta = os_time_get() - basetod.ostime;
os_deltatime(delta, &basetod.uptime, &basetod.uptime);
basetod.utctime = *utctime;
basetod.ostime += delta;
}
if (tz != NULL) {
basetod.timezone = *tz;
}
OS_EXIT_CRITICAL(sr);
return (0);
}
/**
* Get the current time of day. Returns the time of day in UTC
* into the tv argument, and returns the timezone (if set) into
* tz.
*
* @param tv The structure to put the UTC time of day into
* @param tz The structure to put the timezone information into
*
* @return 0 on success, non-zero on failure
*/
int
os_gettimeofday(struct os_timeval *tv, struct os_timezone *tz)
{
os_sr_t sr;
os_time_t delta;
OS_ENTER_CRITICAL(sr);
if (tv != NULL) {
delta = os_time_get() - basetod.ostime;
os_deltatime(delta, &basetod.utctime, tv);
}
if (tz != NULL) {
*tz = basetod.timezone;
}
OS_EXIT_CRITICAL(sr);
return (0);
}
/**
* Get time since boot in microseconds.
*
* @return time since boot in microseconds
*/
int64_t
os_get_uptime_usec(void)
{
struct os_timeval tv;
os_time_t delta;
os_sr_t sr;
os_time_t ostime;
OS_ENTER_CRITICAL(sr);
tv = basetod.uptime;
ostime = basetod.ostime;
delta = os_time_get() - ostime;
OS_EXIT_CRITICAL(sr);
os_deltatime(delta, &tv, &tv);
return(tv.tv_sec * 1000000 + tv.tv_usec);
}
/**
* Converts milliseconds to OS ticks.
*
* @param ms The milliseconds input.
* @param out_ticks The OS ticks output.
*
* @return 0 on success; OS_EINVAL if the result is too
* large to fit in a uint32_t.
*/
int
os_time_ms_to_ticks(uint32_t ms, uint32_t *out_ticks)
{
uint64_t ticks;
#if OS_TICKS_PER_SEC == 1000
*out_ticks = ms;
return 0;
#endif
_Static_assert(OS_TICKS_PER_SEC <= UINT32_MAX,
"OS_TICKS_PER_SEC must be <= UINT32_MAX");
ticks = (uint64_t)ms * OS_TICKS_PER_SEC / 1000;
if (ticks > UINT32_MAX) {
return OS_EINVAL;
}
*out_ticks = ticks;
return 0;
}
/**
* @} OSKernel
* @} OSTime
*/
+64
View File
@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <stdio.h>
#include <stddef.h>
#include <limits.h>
#include "os/os_fault.h"
#include "syscfg/syscfg.h"
#include "sysinit/sysinit.h"
static void
sysinit_dflt_panic_cb(const char *file, int line, const char *func,
const char *expr, const char *msg)
{
#if MYNEWT_VAL(SYSINIT_PANIC_MESSAGE)
if (msg != NULL) {
fprintf(stderr, "sysinit failure: %s\n", msg);
}
#endif
__assert_func(file, line, func, expr);
}
sysinit_panic_fn *sysinit_panic_cb = sysinit_dflt_panic_cb;
uint8_t sysinit_active;
/**
* Sets the sysinit panic function; i.e., the function which executes when
* initialization fails. By default, a panic triggers a failed assertion.
*/
void
sysinit_panic_set(sysinit_panic_fn *panic_cb)
{
sysinit_panic_cb = panic_cb;
}
void
sysinit_start(void)
{
sysinit_active = 1;
}
void
sysinit_end(void)
{
sysinit_active = 0;
}
+257
View File
@@ -0,0 +1,257 @@
PROJECT_NAME := nimble_FreeRTOS_pca10040
TARGETS := nrf52832_xxaa
OUTPUT_DIRECTORY := _build
NRF5_SDK_ROOT ?= ./nrf5_sdk
PROJ_ROOT := ../..
$(OUTPUT_DIRECTORY)/nrf52832_xxaa.out: \
LINKER_SCRIPT := nimble_FreeRTOS_gcc_nrf52.ld
# Source files common to all targets
SRC_FILES += \
$(NRF5_SDK_ROOT)/components/libraries/log/src/nrf_log_backend_serial.c \
$(NRF5_SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \
$(NRF5_SDK_ROOT)/components/libraries/button/app_button.c \
$(NRF5_SDK_ROOT)/components/libraries/util/app_error.c \
$(NRF5_SDK_ROOT)/components/libraries/util/app_error_weak.c \
$(NRF5_SDK_ROOT)/components/libraries/timer/app_timer_freertos.c \
$(NRF5_SDK_ROOT)/components/libraries/util/app_util_platform.c \
$(NRF5_SDK_ROOT)/components/libraries/util/nrf_assert.c \
$(NRF5_SDK_ROOT)/components/libraries/util/sdk_errors.c \
$(NRF5_SDK_ROOT)/external/freertos/source/croutine.c \
$(NRF5_SDK_ROOT)/external/freertos/source/event_groups.c \
$(NRF5_SDK_ROOT)/external/freertos/source/portable/MemMang/heap_1.c \
$(NRF5_SDK_ROOT)/external/freertos/source/list.c \
$(NRF5_SDK_ROOT)/external/freertos/portable/GCC/nrf52/port.c \
$(NRF5_SDK_ROOT)/external/freertos/portable/CMSIS/nrf52/port_cmsis.c \
$(NRF5_SDK_ROOT)/external/freertos/portable/CMSIS/nrf52/port_cmsis_systick.c \
$(NRF5_SDK_ROOT)/external/freertos/source/queue.c \
$(NRF5_SDK_ROOT)/external/freertos/source/tasks.c \
$(NRF5_SDK_ROOT)/external/freertos/source/timers.c \
$(NRF5_SDK_ROOT)/components/boards/boards.c \
$(NRF5_SDK_ROOT)/components/drivers_nrf/clock/nrf_drv_clock.c \
$(NRF5_SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \
$(NRF5_SDK_ROOT)/components/drivers_nrf/gpiote/nrf_drv_gpiote.c \
$(NRF5_SDK_ROOT)/components/drivers_nrf/uart/nrf_drv_uart.c \
$(NRF5_SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c \
$(NRF5_SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c \
$(NRF5_SDK_ROOT)/components/libraries/bsp/bsp.c \
$(NRF5_SDK_ROOT)/components/libraries/bsp/bsp_nfc.c \
$(NRF5_SDK_ROOT)/external/segger_rtt/RTT_Syscalls_GCC.c \
$(NRF5_SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \
$(NRF5_SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \
$(NRF5_SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.S \
$(NRF5_SDK_ROOT)/components/toolchain/system_nrf52.c \
./src/main.c \
./src/ble_task.c \
./src/os_port.c \
./src/cmsis_nvic.c \
./src/hal_timer.c \
$(PROJ_ROOT)/porting/common/src/nimble_port.c \
$(PROJ_ROOT)/porting/common/src/mem/mem.c \
$(PROJ_ROOT)/porting/common/src/os/endian.c \
$(PROJ_ROOT)/porting/common/src/os/os_cputime.c \
$(PROJ_ROOT)/porting/common/src/os/os_cputime_pwr2.c \
$(PROJ_ROOT)/porting/common/src/os/os_mbuf.c \
$(PROJ_ROOT)/porting/common/src/os/os_mempool.c \
$(PROJ_ROOT)/porting/common/src/os/os_msys_init.c \
$(PROJ_ROOT)/porting/common/src/sysinit/sysinit.c \
$(PROJ_ROOT)/nimble/src/ble_util.c \
$(PROJ_ROOT)/nimble/src/hci_common.c \
$(PROJ_ROOT)/nimble/host/src/ble_att_clt.c \
$(PROJ_ROOT)/nimble/host/src/ble_att_cmd.c \
$(PROJ_ROOT)/nimble/host/src/ble_att.c \
$(PROJ_ROOT)/nimble/host/src/ble_att_svr.c \
$(PROJ_ROOT)/nimble/host/src/ble_eddystone.c \
$(PROJ_ROOT)/nimble/host/src/ble_gap.c \
$(PROJ_ROOT)/nimble/host/src/ble_gattc.c \
$(PROJ_ROOT)/nimble/host/src/ble_gatts_lcl.c \
$(PROJ_ROOT)/nimble/host/src/ble_gatts.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_adv.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_atomic.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_cfg.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_conn.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_dbg.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_hci_cmd.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_hci_evt.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_hci.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_hci_util.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_id.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_log.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_mbuf.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_misc.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_pvcy.c \
$(PROJ_ROOT)/nimble/host/src/ble_hs_startup.c \
$(PROJ_ROOT)/nimble/host/src/ble_ibeacon.c \
$(PROJ_ROOT)/nimble/host/src/ble_l2cap_coc.c \
$(PROJ_ROOT)/nimble/host/src/ble_l2cap.c \
$(PROJ_ROOT)/nimble/host/src/ble_l2cap_sig_cmd.c \
$(PROJ_ROOT)/nimble/host/src/ble_l2cap_sig.c \
$(PROJ_ROOT)/nimble/host/src/ble_monitor.c \
$(PROJ_ROOT)/nimble/host/src/ble_sm_alg.c \
$(PROJ_ROOT)/nimble/host/src/ble_sm_cmd.c \
$(PROJ_ROOT)/nimble/host/src/ble_sm_lgcy.c \
$(PROJ_ROOT)/nimble/host/src/ble_sm.c \
$(PROJ_ROOT)/nimble/host/src/ble_sm_sc.c \
$(PROJ_ROOT)/nimble/host/src/ble_store.c \
$(PROJ_ROOT)/nimble/host/src/ble_store_util.c \
$(PROJ_ROOT)/nimble/host/src/ble_uuid.c \
$(PROJ_ROOT)/nimble/host/src/ble_uuid.c \
$(PROJ_ROOT)/nimble/host/services/ans/src/ble_svc_ans.c \
$(PROJ_ROOT)/nimble/host/services/gap/src/ble_svc_gap.c \
$(PROJ_ROOT)/nimble/host/services/gatt/src/ble_svc_gatt.c \
$(PROJ_ROOT)/nimble/host/services/ias/src/ble_svc_ias.c \
$(PROJ_ROOT)/nimble/host/services/lls/src/ble_svc_lls.c \
$(PROJ_ROOT)/nimble/host/services/tps/src/ble_svc_tps.c \
$(PROJ_ROOT)/nimble/host/store/ram/src/ble_store_ram.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_sched.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_xcvr.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_whitelist.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_ctrl.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_hci.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_supp_cmd.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_adv.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_conn.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_resolv.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_conn_hci.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_rand.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_scan.c \
$(PROJ_ROOT)/nimble/controller/src/ble_ll_hci_ev.c \
$(PROJ_ROOT)/nimble/transport/ram/src/ble_hci_ram.c \
$(PROJ_ROOT)/nimble/drivers/nrf52/src/ble_hw.c \
$(PROJ_ROOT)/nimble/drivers/nrf52/src/ble_phy.c \
$(PROJ_ROOT)/tinycrypt/src/aes_decrypt.c \
$(PROJ_ROOT)/tinycrypt/src/aes_encrypt.c \
$(PROJ_ROOT)/tinycrypt/src/cmac_mode.c \
$(PROJ_ROOT)/tinycrypt/src/ecc.c \
$(PROJ_ROOT)/tinycrypt/src/ecc_dh.c \
$(PROJ_ROOT)/tinycrypt/src/utils.c \
# Include folders common to all targets
INC_FOLDERS += \
./config \
$(NRF5_SDK_ROOT)/components \
$(NRF5_SDK_ROOT)/components/toolchain/cmsis/include \
$(NRF5_SDK_ROOT)/external/freertos/source/include \
$(NRF5_SDK_ROOT)/external/freertos/config \
$(NRF5_SDK_ROOT)/components/libraries/util \
$(NRF5_SDK_ROOT)/components/drivers_nrf/uart \
$(NRF5_SDK_ROOT)/components/libraries/bsp \
$(NRF5_SDK_ROOT)/components/device \
$(NRF5_SDK_ROOT)/components/libraries/log \
$(NRF5_SDK_ROOT)/components/libraries/button \
$(NRF5_SDK_ROOT)/components/libraries/timer \
$(NRF5_SDK_ROOT)/external/freertos/portable/CMSIS/nrf52 \
$(NRF5_SDK_ROOT)/components/drivers_nrf/gpiote \
$(NRF5_SDK_ROOT)/external/segger_rtt \
$(NRF5_SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd \
$(NRF5_SDK_ROOT)/components/boards \
$(NRF5_SDK_ROOT)/components/drivers_nrf/hal \
$(NRF5_SDK_ROOT)/components/toolchain/gcc \
$(NRF5_SDK_ROOT)/components/toolchain \
$(NRF5_SDK_ROOT)/components/drivers_nrf/common \
$(NRF5_SDK_ROOT)/components/drivers_nrf/clock \
$(NRF5_SDK_ROOT)/external/freertos/portable/GCC/nrf52 \
$(NRF5_SDK_ROOT)/components/libraries/log/src \
./include \
$(PROJ_ROOT)/porting/common/include \
$(PROJ_ROOT)/nimble/include \
$(PROJ_ROOT)/nimble/host/include \
$(PROJ_ROOT)/nimble/host/mesh/include \
$(PROJ_ROOT)/nimble/host/services/ans/include \
$(PROJ_ROOT)/nimble/host/services/gap/include \
$(PROJ_ROOT)/nimble/host/services/gatt/include \
$(PROJ_ROOT)/nimble/host/services/ias/include \
$(PROJ_ROOT)/nimble/host/services/lls/include \
$(PROJ_ROOT)/nimble/host/services/tps/include \
$(PROJ_ROOT)/nimble/host/store/ram/include \
$(PROJ_ROOT)/nimble/controller/include \
$(PROJ_ROOT)/nimble/transport/ram/include \
$(PROJ_ROOT)/nimble/drivers/nrf52/include \
$(PROJ_ROOT)/tinycrypt/include \
# Libraries common to all targets
LIB_FILES += \
# C flags common to all targets
CFLAGS += -DNRF52_PAN_12
CFLAGS += -DNRF52_PAN_15
CFLAGS += -DNRF52_PAN_58
CFLAGS += -DFREERTOS
CFLAGS += -DNRF52_PAN_20
CFLAGS += -DNRF52_PAN_54
CFLAGS += -DNRF52
CFLAGS += -DNRF52_PAN_51
CFLAGS += -DNRF52_PAN_36
CFLAGS += -DCONFIG_GPIO_AS_PINRESET
CFLAGS += -DNRF52_PAN_64
CFLAGS += -DNRF52_PAN_55
CFLAGS += -DBOARD_PCA10040
CFLAGS += -DNRF52_PAN_31
CFLAGS += -DNRF52832
CFLAGS += -mcpu=cortex-m4
CFLAGS += -mthumb -mabi=aapcs
CFLAGS += -Wall -Werror -Og -g3
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# keep every function in separate section, this allows linker to discard unused ones
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CFLAGS += -fno-builtin --short-enums
# C++ flags common to all targets
CXXFLAGS += \
# Assembler flags common to all targets
ASMFLAGS += -x assembler-with-cpp
ASMFLAGS += -DNRF52_PAN_12
ASMFLAGS += -DNRF52_PAN_15
ASMFLAGS += -DNRF52_PAN_58
ASMFLAGS += -DFREERTOS
ASMFLAGS += -DNRF52_PAN_20
ASMFLAGS += -DNRF52_PAN_54
ASMFLAGS += -DNRF52
ASMFLAGS += -DNRF52_PAN_51
ASMFLAGS += -DNRF52_PAN_36
ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
ASMFLAGS += -DNRF52_PAN_64
ASMFLAGS += -DNRF52_PAN_55
ASMFLAGS += -DBOARD_PCA10040
ASMFLAGS += -DNRF52_PAN_31
ASMFLAGS += -DNRF52832
# Linker flags
LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m4
LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# let linker to dump unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs -lc -lnosys
.PHONY: $(TARGETS) default all clean help flash
# Default target - first one defined
default: nrf52832_xxaa
# Print all targets that can be built
help:
@echo following targets are available:
@echo nrf52832_xxaa
TEMPLATE_PATH := $(NRF5_SDK_ROOT)/components/toolchain/gcc
include $(TEMPLATE_PATH)/Makefile.common
$(foreach target, $(TARGETS), $(call define_target, $(target)))
# Flash the program
flash: $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex
@echo Flashing: $<
nrfjprog --program $< -f nrf52 --sectorerase
nrfjprog --reset -f nrf52
erase:
nrfjprog --eraseall -f nrf52
@@ -0,0 +1,229 @@
/*
FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#endif
/*-----------------------------------------------------------
* Possible configurations for system timer
*/
#define FREERTOS_USE_RTC 0 /**< Use real time clock for the system */
#define FREERTOS_USE_SYSTICK 1 /**< Use SysTick timer for system */
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#define configTICK_SOURCE FREERTOS_USE_RTC
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configUSE_TICKLESS_IDLE 1
#define configUSE_TICKLESS_IDLE_SIMPLE_DEBUG 1 /* See into vPortSuppressTicksAndSleep source code for explanation */
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES ( 3 )
#define configMINIMAL_STACK_SIZE ( 60 )
#define configTOTAL_HEAP_SIZE ( 6144 )
#define configMAX_TASK_NAME_LEN ( 4 )
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE 2
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 1
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH ( 80 )
/* Tickless Idle configuration. */
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
/* Tickless idle/low power functionality. */
/* Define to trap errors during development. */
#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)
#define configASSERT( x ) ASSERT(x)
#endif
/* FreeRTOS MPU specific definitions. */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 1
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
#define INCLUDE_pcTaskGetTaskName 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY configLIBRARY_LOWEST_INTERRUPT_PRIORITY
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names - or at least those used in the unmodified vector table. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
/*-----------------------------------------------------------
* Settings that are generated automatically
* basing on the settings above
*/
#if (configTICK_SOURCE == FREERTOS_USE_SYSTICK)
// do not define configSYSTICK_CLOCK_HZ for SysTick to be configured automatically
// to CPU clock source
#define xPortSysTickHandler SysTick_Handler
#elif (configTICK_SOURCE == FREERTOS_USE_RTC)
#define configSYSTICK_CLOCK_HZ ( 32768UL )
#define xPortSysTickHandler RTC1_IRQHandler
#else
#error Unsupported configTICK_SOURCE value
#endif
/* Code below should be only used by the compiler, and not the assembler. */
#if !(defined(__ASSEMBLY__) || defined(__ASSEMBLER__))
#include "nrf.h"
#include "nrf_assert.h"
/* This part of definitions may be problematic in assembly - it uses definitions from files that are not assembly compatible. */
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#error "This port requires __NVIC_PRIO_BITS to be defined"
#endif
/* Access to current system core clock is required only if we are ticking the system by systimer */
#if (configTICK_SOURCE == FREERTOS_USE_SYSTICK)
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#endif /* !assembler */
#endif /* FREERTOS_CONFIG_H */
@@ -0,0 +1,699 @@
#ifndef SDK_CONFIG_H
#define SDK_CONFIG_H
// <<< Use Configuration Wizard in Context Menu >>>\n
#ifdef USE_APP_CONFIG
#include "app_config.h"
#endif
// <h> nRF_Drivers
//==========================================================
// <e> CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver
//==========================================================
#ifndef CLOCK_ENABLED
#define CLOCK_ENABLED 1
#endif
#if CLOCK_ENABLED
// <o> CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency
// <0=> Default (64 MHz)
#ifndef CLOCK_CONFIG_XTAL_FREQ
#define CLOCK_CONFIG_XTAL_FREQ 0
#endif
// <o> CLOCK_CONFIG_LF_SRC - LF Clock Source
// <0=> RC
// <1=> XTAL
// <2=> Synth
#ifndef CLOCK_CONFIG_LF_SRC
#define CLOCK_CONFIG_LF_SRC 1
#endif
// <o> CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority
// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7
#ifndef CLOCK_CONFIG_IRQ_PRIORITY
#define CLOCK_CONFIG_IRQ_PRIORITY 7
#endif
// <e> CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef CLOCK_CONFIG_LOG_ENABLED
#define CLOCK_CONFIG_LOG_ENABLED 0
#endif
#if CLOCK_CONFIG_LOG_ENABLED
// <o> CLOCK_CONFIG_LOG_LEVEL - Default Severity level
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef CLOCK_CONFIG_LOG_LEVEL
#define CLOCK_CONFIG_LOG_LEVEL 3
#endif
// <o> CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef CLOCK_CONFIG_INFO_COLOR
#define CLOCK_CONFIG_INFO_COLOR 0
#endif
// <o> CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef CLOCK_CONFIG_DEBUG_COLOR
#define CLOCK_CONFIG_DEBUG_COLOR 0
#endif
#endif //CLOCK_CONFIG_LOG_ENABLED
// </e>
#endif //CLOCK_ENABLED
// </e>
// <e> GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver
//==========================================================
#ifndef GPIOTE_ENABLED
#define GPIOTE_ENABLED 1
#endif
#if GPIOTE_ENABLED
// <o> GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins
#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS
#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4
#endif
// <o> GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority
// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7
#ifndef GPIOTE_CONFIG_IRQ_PRIORITY
#define GPIOTE_CONFIG_IRQ_PRIORITY 7
#endif
// <e> GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef GPIOTE_CONFIG_LOG_ENABLED
#define GPIOTE_CONFIG_LOG_ENABLED 0
#endif
#if GPIOTE_CONFIG_LOG_ENABLED
// <o> GPIOTE_CONFIG_LOG_LEVEL - Default Severity level
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef GPIOTE_CONFIG_LOG_LEVEL
#define GPIOTE_CONFIG_LOG_LEVEL 3
#endif
// <o> GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef GPIOTE_CONFIG_INFO_COLOR
#define GPIOTE_CONFIG_INFO_COLOR 0
#endif
// <o> GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef GPIOTE_CONFIG_DEBUG_COLOR
#define GPIOTE_CONFIG_DEBUG_COLOR 0
#endif
#endif //GPIOTE_CONFIG_LOG_ENABLED
// </e>
#endif //GPIOTE_ENABLED
// </e>
// <e> PERIPHERAL_RESOURCE_SHARING_ENABLED - nrf_drv_common - Peripheral drivers common module
//==========================================================
#ifndef PERIPHERAL_RESOURCE_SHARING_ENABLED
#define PERIPHERAL_RESOURCE_SHARING_ENABLED 0
#endif
#if PERIPHERAL_RESOURCE_SHARING_ENABLED
// <e> COMMON_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef COMMON_CONFIG_LOG_ENABLED
#define COMMON_CONFIG_LOG_ENABLED 0
#endif
#if COMMON_CONFIG_LOG_ENABLED
// <o> COMMON_CONFIG_LOG_LEVEL - Default Severity level
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef COMMON_CONFIG_LOG_LEVEL
#define COMMON_CONFIG_LOG_LEVEL 3
#endif
// <o> COMMON_CONFIG_INFO_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef COMMON_CONFIG_INFO_COLOR
#define COMMON_CONFIG_INFO_COLOR 0
#endif
// <o> COMMON_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef COMMON_CONFIG_DEBUG_COLOR
#define COMMON_CONFIG_DEBUG_COLOR 0
#endif
#endif //COMMON_CONFIG_LOG_ENABLED
// </e>
#endif //PERIPHERAL_RESOURCE_SHARING_ENABLED
// </e>
// <e> UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver
//==========================================================
#ifndef UART_ENABLED
#define UART_ENABLED 1
#endif
#if UART_ENABLED
// <o> UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control
// <0=> Disabled
// <1=> Enabled
#ifndef UART_DEFAULT_CONFIG_HWFC
#define UART_DEFAULT_CONFIG_HWFC 0
#endif
// <o> UART_DEFAULT_CONFIG_PARITY - Parity
// <0=> Excluded
// <14=> Included
#ifndef UART_DEFAULT_CONFIG_PARITY
#define UART_DEFAULT_CONFIG_PARITY 0
#endif
// <o> UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate
// <323584=> 1200 baud
// <643072=> 2400 baud
// <1290240=> 4800 baud
// <2576384=> 9600 baud
// <3862528=> 14400 baud
// <5152768=> 19200 baud
// <7716864=> 28800 baud
// <10289152=> 38400 baud
// <15400960=> 57600 baud
// <20615168=> 76800 baud
// <30801920=> 115200 baud
// <61865984=> 230400 baud
// <67108864=> 250000 baud
// <121634816=> 460800 baud
// <251658240=> 921600 baud
// <268435456=> 57600 baud
#ifndef UART_DEFAULT_CONFIG_BAUDRATE
#define UART_DEFAULT_CONFIG_BAUDRATE 30801920
#endif
// <o> UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority
// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7
#ifndef UART_DEFAULT_CONFIG_IRQ_PRIORITY
#define UART_DEFAULT_CONFIG_IRQ_PRIORITY 7
#endif
// <q> UART_EASY_DMA_SUPPORT - Driver supporting EasyDMA
#ifndef UART_EASY_DMA_SUPPORT
#define UART_EASY_DMA_SUPPORT 1
#endif
// <q> UART_LEGACY_SUPPORT - Driver supporting Legacy mode
#ifndef UART_LEGACY_SUPPORT
#define UART_LEGACY_SUPPORT 1
#endif
// <e> UART0_ENABLED - Enable UART0 instance
//==========================================================
#ifndef UART0_ENABLED
#define UART0_ENABLED 1
#endif
#if UART0_ENABLED
// <q> UART0_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA
#ifndef UART0_CONFIG_USE_EASY_DMA
#define UART0_CONFIG_USE_EASY_DMA 1
#endif
#endif //UART0_ENABLED
// </e>
// <e> UART_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef UART_CONFIG_LOG_ENABLED
#define UART_CONFIG_LOG_ENABLED 0
#endif
#if UART_CONFIG_LOG_ENABLED
// <o> UART_CONFIG_LOG_LEVEL - Default Severity level
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef UART_CONFIG_LOG_LEVEL
#define UART_CONFIG_LOG_LEVEL 3
#endif
// <o> UART_CONFIG_INFO_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef UART_CONFIG_INFO_COLOR
#define UART_CONFIG_INFO_COLOR 0
#endif
// <o> UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef UART_CONFIG_DEBUG_COLOR
#define UART_CONFIG_DEBUG_COLOR 0
#endif
#endif //UART_CONFIG_LOG_ENABLED
// </e>
#endif //UART_ENABLED
// </e>
// </h>
//==========================================================
// <h> nRF_Libraries
//==========================================================
// <e> APP_TIMER_ENABLED - app_timer - Application timer functionality
//==========================================================
#ifndef APP_TIMER_ENABLED
#define APP_TIMER_ENABLED 1
#endif
#if APP_TIMER_ENABLED
// <q> APP_TIMER_WITH_PROFILER - Enable app_timer profiling
#ifndef APP_TIMER_WITH_PROFILER
#define APP_TIMER_WITH_PROFILER 0
#endif
// <q> APP_TIMER_KEEPS_RTC_ACTIVE - Enable RTC always on
// <i> If option is enabled RTC is kept running even if there is no active timers.
// <i> This option can be used when app_timer is used for timestamping.
#ifndef APP_TIMER_KEEPS_RTC_ACTIVE
#define APP_TIMER_KEEPS_RTC_ACTIVE 0
#endif
#endif //APP_TIMER_ENABLED
// </e>
// <q> BUTTON_ENABLED - app_button - buttons handling module
#ifndef BUTTON_ENABLED
#define BUTTON_ENABLED 1
#endif
// </h>
//==========================================================
// <h> nRF_Log
//==========================================================
// <e> NRF_LOG_ENABLED - nrf_log - Logging
//==========================================================
#ifndef NRF_LOG_ENABLED
#define NRF_LOG_ENABLED 0
#endif
#if NRF_LOG_ENABLED
// <e> NRF_LOG_USES_COLORS - If enabled then ANSI escape code for colors is prefixed to every string
//==========================================================
#ifndef NRF_LOG_USES_COLORS
#define NRF_LOG_USES_COLORS 0
#endif
#if NRF_LOG_USES_COLORS
// <o> NRF_LOG_COLOR_DEFAULT - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef NRF_LOG_COLOR_DEFAULT
#define NRF_LOG_COLOR_DEFAULT 0
#endif
// <o> NRF_LOG_ERROR_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef NRF_LOG_ERROR_COLOR
#define NRF_LOG_ERROR_COLOR 0
#endif
// <o> NRF_LOG_WARNING_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef NRF_LOG_WARNING_COLOR
#define NRF_LOG_WARNING_COLOR 0
#endif
#endif //NRF_LOG_USES_COLORS
// </e>
// <o> NRF_LOG_DEFAULT_LEVEL - Default Severity level
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef NRF_LOG_DEFAULT_LEVEL
#define NRF_LOG_DEFAULT_LEVEL 3
#endif
// <e> NRF_LOG_DEFERRED - Enable deffered logger.
// <i> Log data is buffered and can be processed in idle.
//==========================================================
#ifndef NRF_LOG_DEFERRED
#define NRF_LOG_DEFERRED 1
#endif
#if NRF_LOG_DEFERRED
// <o> NRF_LOG_DEFERRED_BUFSIZE - Size of the buffer for logs in words.
// <i> Must be power of 2
#ifndef NRF_LOG_DEFERRED_BUFSIZE
#define NRF_LOG_DEFERRED_BUFSIZE 256
#endif
#endif //NRF_LOG_DEFERRED
// </e>
// <q> NRF_LOG_USES_TIMESTAMP - Enable timestamping
// <i> Function for getting the timestamp is provided by the user
#ifndef NRF_LOG_USES_TIMESTAMP
#define NRF_LOG_USES_TIMESTAMP 0
#endif
#endif //NRF_LOG_ENABLED
// </e>
// <h> nrf_log_backend - Logging sink
//==========================================================
// <o> NRF_LOG_BACKEND_MAX_STRING_LENGTH - Buffer for storing single output string
// <i> Logger backend RAM usage is determined by this value.
#ifndef NRF_LOG_BACKEND_MAX_STRING_LENGTH
#define NRF_LOG_BACKEND_MAX_STRING_LENGTH 256
#endif
// <o> NRF_LOG_TIMESTAMP_DIGITS - Number of digits for timestamp
// <i> If higher resolution timestamp source is used it might be needed to increase that
#ifndef NRF_LOG_TIMESTAMP_DIGITS
#define NRF_LOG_TIMESTAMP_DIGITS 8
#endif
// <e> NRF_LOG_BACKEND_SERIAL_USES_UART - If enabled data is printed over UART
//==========================================================
#ifndef NRF_LOG_BACKEND_SERIAL_USES_UART
#define NRF_LOG_BACKEND_SERIAL_USES_UART 1
#endif
#if NRF_LOG_BACKEND_SERIAL_USES_UART
// <o> NRF_LOG_BACKEND_SERIAL_UART_BAUDRATE - Default Baudrate
// <323584=> 1200 baud
// <643072=> 2400 baud
// <1290240=> 4800 baud
// <2576384=> 9600 baud
// <3862528=> 14400 baud
// <5152768=> 19200 baud
// <7716864=> 28800 baud
// <10289152=> 38400 baud
// <15400960=> 57600 baud
// <20615168=> 76800 baud
// <30801920=> 115200 baud
// <61865984=> 230400 baud
// <67108864=> 250000 baud
// <121634816=> 460800 baud
// <251658240=> 921600 baud
// <268435456=> 57600 baud
#ifndef NRF_LOG_BACKEND_SERIAL_UART_BAUDRATE
#define NRF_LOG_BACKEND_SERIAL_UART_BAUDRATE 30801920
#endif
// <o> NRF_LOG_BACKEND_SERIAL_UART_TX_PIN - UART TX pin
#ifndef NRF_LOG_BACKEND_SERIAL_UART_TX_PIN
#define NRF_LOG_BACKEND_SERIAL_UART_TX_PIN 6
#endif
// <o> NRF_LOG_BACKEND_SERIAL_UART_RX_PIN - UART RX pin
#ifndef NRF_LOG_BACKEND_SERIAL_UART_RX_PIN
#define NRF_LOG_BACKEND_SERIAL_UART_RX_PIN 8
#endif
// <o> NRF_LOG_BACKEND_SERIAL_UART_RTS_PIN - UART RTS pin
#ifndef NRF_LOG_BACKEND_SERIAL_UART_RTS_PIN
#define NRF_LOG_BACKEND_SERIAL_UART_RTS_PIN 5
#endif
// <o> NRF_LOG_BACKEND_SERIAL_UART_CTS_PIN - UART CTS pin
#ifndef NRF_LOG_BACKEND_SERIAL_UART_CTS_PIN
#define NRF_LOG_BACKEND_SERIAL_UART_CTS_PIN 7
#endif
// <o> NRF_LOG_BACKEND_SERIAL_UART_FLOW_CONTROL - Hardware Flow Control
// <0=> Disabled
// <1=> Enabled
#ifndef NRF_LOG_BACKEND_SERIAL_UART_FLOW_CONTROL
#define NRF_LOG_BACKEND_SERIAL_UART_FLOW_CONTROL 0
#endif
// <o> NRF_LOG_BACKEND_UART_INSTANCE - UART instance used
// <0=> 0
#ifndef NRF_LOG_BACKEND_UART_INSTANCE
#define NRF_LOG_BACKEND_UART_INSTANCE 0
#endif
#endif //NRF_LOG_BACKEND_SERIAL_USES_UART
// </e>
// <e> NRF_LOG_BACKEND_SERIAL_USES_RTT - If enabled data is printed using RTT
//==========================================================
#ifndef NRF_LOG_BACKEND_SERIAL_USES_RTT
#define NRF_LOG_BACKEND_SERIAL_USES_RTT 0
#endif
#if NRF_LOG_BACKEND_SERIAL_USES_RTT
// <o> NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE - RTT output buffer size.
// <i> Should be equal or bigger than \ref NRF_LOG_BACKEND_MAX_STRING_LENGTH.
// <i> This value is used in Segger RTT configuration to set the buffer size
// <i> if it is bigger than default RTT buffer size.
#ifndef NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE
#define NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE 512
#endif
#endif //NRF_LOG_BACKEND_SERIAL_USES_RTT
// </e>
// </h>
//==========================================================
// </h>
//==========================================================
// <h> nRF_Segger_RTT
//==========================================================
// <h> segger_rtt - SEGGER RTT
//==========================================================
// <o> SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer.
#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP
#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 64
#endif
// <o> SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Size of upstream buffer.
#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS
#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2
#endif
// <o> SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of upstream buffer.
#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN
#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16
#endif
// <o> SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Size of upstream buffer.
#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS
#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2
#endif
// </h>
//==========================================================
// </h>
//==========================================================
// <<< end of configuration section >>>
#endif //SDK_CONFIG_H
@@ -0,0 +1,29 @@
/* mbed Microcontroller Library - cmsis_nvic
* Copyright (c) 2009-2011 ARM Limited. All rights reserved.
*
* CMSIS-style functionality to support dynamic vectors
*/
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#include <stdint.h>
#define NVIC_NUM_VECTORS (16 + 38) // CORE + MCU Peripherals
#define NVIC_USER_IRQ_OFFSET 16
#include "nrf52.h"
#ifdef __cplusplus
extern "C" {
#endif
void NVIC_Relocate(void);
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
uint32_t NVIC_GetVector(IRQn_Type IRQn);
#ifdef __cplusplus
}
#endif
#endif
+70
View File
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 H_NRF52_HAL_
#define H_NRF52_HAL_
#ifdef __cplusplus
extern "C" {
#endif
/* Helper functions to enable/disable interrupts. */
#define __HAL_DISABLE_INTERRUPTS(x) \
do { \
x = __get_PRIMASK(); \
__disable_irq(); \
} while(0);
#define __HAL_ENABLE_INTERRUPTS(x) \
do { \
if (!x) { \
__enable_irq(); \
} \
} while(0);
struct nrf52_uart_cfg {
int8_t suc_pin_tx; /* pins for IO */
int8_t suc_pin_rx;
int8_t suc_pin_rts;
int8_t suc_pin_cts;
};
const struct nrf52_uart_cfg *bsp_uart_config(void);
struct nrf52_hal_i2c_cfg {
int scl_pin;
int sda_pin;
uint32_t i2c_frequency;
};
struct hal_flash;
extern const struct hal_flash nrf52k_flash_dev;
/* SPI configuration (used for both master and slave) */
struct nrf52_hal_spi_cfg {
uint8_t sck_pin;
uint8_t mosi_pin;
uint8_t miso_pin;
uint8_t ss_pin;
};
#ifdef __cplusplus
}
#endif
#endif /* H_NRF52_HAL_ */
+25
View File
@@ -0,0 +1,25 @@
#ifndef _OS_ARCH_H
#define _OS_ARCH_H
#include <stdint.h>
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef int os_sr_t;
typedef int os_stack_t;
#define OS_ALIGNMENT (4)
#define OS_TICKS_PER_SEC (configTICK_RATE_HZ)
#define OS_ENTER_CRITICAL(unused) do { (void)unused; vPortEnterCritical(); } while (0)
#define OS_EXIT_CRITICAL(unused) do { (void)unused; vPortExitCritical(); } while (0)
#ifdef __cplusplus
}
#endif
#endif /* _OS_ARCH_H */
@@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_CALLOUT_H
#define _OS_CALLOUT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "os/os_eventq.h"
#include "FreeRTOS.h"
#include "timers.h"
struct os_callout {
struct os_event c_ev;
struct os_eventq *c_evq;
uint32_t c_ticks;
TimerHandle_t c_timer;
};
void os_callout_init(struct os_callout *cf, struct os_eventq *evq,
os_event_fn *ev_cb, void *ev_arg);
int os_callout_reset(struct os_callout *, int32_t);
int os_callout_queued(struct os_callout *c);
void os_callout_stop(struct os_callout *c);
#ifdef __cplusplus
}
#endif
#endif /* _OS_CALLOUT_H */
@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_EVENTQ_H
#define _OS_EVENTQ_H
#include <inttypes.h>
#include "os/os_time.h"
#include "os/queue.h"
#include "FreeRTOS.h"
#include "queue.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_event;
typedef void os_event_fn(struct os_event *ev);
struct os_event {
uint8_t ev_queued;
os_event_fn *ev_cb;
void *ev_arg;
};
#define OS_EVENT_QUEUED(__ev) ((__ev)->ev_queued)
struct os_eventq {
QueueHandle_t q;
};
void os_eventq_init(struct os_eventq *);
int os_eventq_inited(const struct os_eventq *evq);
void os_eventq_put(struct os_eventq *, struct os_event *);
struct os_event *os_eventq_get_no_wait(struct os_eventq *evq);
struct os_event *os_eventq_get(struct os_eventq *);
void os_eventq_run(struct os_eventq *evq);
struct os_event *os_eventq_poll(struct os_eventq **, int, os_time_t);
void os_eventq_remove(struct os_eventq *, struct os_event *);
struct os_eventq *os_eventq_dflt_get(void);
/* [DEPRECATED] */
void os_eventq_designate(struct os_eventq **dst, struct os_eventq *val,
struct os_event *start_ev);
#ifdef __cplusplus
}
#endif
#endif /* _OS_EVENTQ_H */
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 _OS_MUTEX_H_
#define _OS_MUTEX_H_
#include "os/os.h"
#include "FreeRTOS.h"
#include "semphr.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_mutex
{
SemaphoreHandle_t handle;
};
os_error_t os_mutex_init(struct os_mutex *mu);
os_error_t os_mutex_release(struct os_mutex *mu);
os_error_t os_mutex_pend(struct os_mutex *mu, uint32_t timeout);
#ifdef __cplusplus
}
#endif
#endif /* _OS_MUTEX_H_ */
@@ -0,0 +1,27 @@
#ifndef _OS_SEM_H_
#define _OS_SEM_H_
#include "os/os_error.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "FreeRTOS.h"
#include "semphr.h"
struct os_sem
{
SemaphoreHandle_t handle;
};
os_error_t os_sem_init(struct os_sem *sem, uint16_t tokens);
os_error_t os_sem_release(struct os_sem *sem);
os_error_t os_sem_pend(struct os_sem *sem, uint32_t timeout);
uint16_t os_sem_get_count(struct os_sem *sem);
#ifdef __cplusplus
}
#endif
#endif /* _OS_SEM_H_ */
@@ -0,0 +1,967 @@
/**
* This file was generated by Apache Newt version: 1.2.0-dev
*/
#ifndef H_MYNEWT_SYSCFG_
#define H_MYNEWT_SYSCFG_
/**
* This macro exists to ensure code includes this header when needed. If code
* checks the existence of a setting directly via ifdef without including this
* header, the setting macro will silently evaluate to 0. In contrast, an
* attempt to use these macros without including this header will result in a
* compiler error.
*/
#define MYNEWT_VAL(x) MYNEWT_VAL_ ## x
/*** compiler/arm-none-eabi-m4 */
#ifndef MYNEWT_VAL_HARDFLOAT
#define MYNEWT_VAL_HARDFLOAT (0)
#endif
/*** hw/bsp/nrf52840pdk */
#ifndef MYNEWT_VAL_BSP_NRF52840
#define MYNEWT_VAL_BSP_NRF52840 (1)
#endif
#ifndef MYNEWT_VAL_TIMER_0
#define MYNEWT_VAL_TIMER_0 (1)
#endif
#ifndef MYNEWT_VAL_TIMER_1
#define MYNEWT_VAL_TIMER_1 (0)
#endif
#ifndef MYNEWT_VAL_TIMER_2
#define MYNEWT_VAL_TIMER_2 (0)
#endif
#ifndef MYNEWT_VAL_TIMER_3
#define MYNEWT_VAL_TIMER_3 (0)
#endif
#ifndef MYNEWT_VAL_TIMER_4
#define MYNEWT_VAL_TIMER_4 (0)
#endif
#ifndef MYNEWT_VAL_TIMER_5
#define MYNEWT_VAL_TIMER_5 (1)
#endif
#ifndef MYNEWT_VAL_UART_0
#define MYNEWT_VAL_UART_0 (1)
#endif
#ifndef MYNEWT_VAL_UART_0_PIN_CTS
#define MYNEWT_VAL_UART_0_PIN_CTS (7)
#endif
#ifndef MYNEWT_VAL_UART_0_PIN_RTS
#define MYNEWT_VAL_UART_0_PIN_RTS (5)
#endif
#ifndef MYNEWT_VAL_UART_0_PIN_RX
#define MYNEWT_VAL_UART_0_PIN_RX (8)
#endif
#ifndef MYNEWT_VAL_UART_0_PIN_TX
#define MYNEWT_VAL_UART_0_PIN_TX (6)
#endif
#ifndef MYNEWT_VAL_UART_1
#define MYNEWT_VAL_UART_1 (0)
#endif
#ifndef MYNEWT_VAL_UART_1_PIN_RX
#define MYNEWT_VAL_UART_1_PIN_RX (-1)
#endif
#ifndef MYNEWT_VAL_UART_1_PIN_TX
#define MYNEWT_VAL_UART_1_PIN_TX (-1)
#endif
/*** hw/drivers/nimble/nrf52 */
#ifndef MYNEWT_VAL_BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN
#define MYNEWT_VAL_BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN (0)
#endif
#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN
#define MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN (-1)
#endif
#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_TXRXEN_READY_PIN
#define MYNEWT_VAL_BLE_PHY_DBG_TIME_TXRXEN_READY_PIN (-1)
#endif
#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_WFR_PIN
#define MYNEWT_VAL_BLE_PHY_DBG_TIME_WFR_PIN (-1)
#endif
/*** hw/mcu/nordic/nrf52xxx */
#ifndef MYNEWT_VAL_I2C_0
#define MYNEWT_VAL_I2C_0 (0)
#endif
#ifndef MYNEWT_VAL_I2C_1
#define MYNEWT_VAL_I2C_1 (0)
#endif
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
#ifndef MYNEWT_VAL_MCU_DCDC_ENABLED
#define MYNEWT_VAL_MCU_DCDC_ENABLED (1)
#endif
#ifndef MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE
#define MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE (1)
#endif
#ifndef MYNEWT_VAL_SPI_0_MASTER
#define MYNEWT_VAL_SPI_0_MASTER (0)
#endif
#ifndef MYNEWT_VAL_SPI_0_SLAVE
#define MYNEWT_VAL_SPI_0_SLAVE (0)
#endif
#ifndef MYNEWT_VAL_SPI_1_MASTER
#define MYNEWT_VAL_SPI_1_MASTER (0)
#endif
#ifndef MYNEWT_VAL_SPI_1_SLAVE
#define MYNEWT_VAL_SPI_1_SLAVE (0)
#endif
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
#ifndef MYNEWT_VAL_XTAL_32768
#define MYNEWT_VAL_XTAL_32768 (1)
#endif
#ifndef MYNEWT_VAL_XTAL_32768_SYNTH
#define MYNEWT_VAL_XTAL_32768_SYNTH (0)
#endif
#ifndef MYNEWT_VAL_XTAL_RC
#define MYNEWT_VAL_XTAL_RC (0)
#endif
/*** kernel/os */
#ifndef MYNEWT_VAL_FLOAT_USER
#define MYNEWT_VAL_FLOAT_USER (0)
#endif
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT
#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12)
#endif
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE
#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292)
#endif
#ifndef MYNEWT_VAL_MSYS_2_BLOCK_COUNT
#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0)
#endif
#ifndef MYNEWT_VAL_MSYS_2_BLOCK_SIZE
#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0)
#endif
#ifndef MYNEWT_VAL_OS_CLI
#define MYNEWT_VAL_OS_CLI (0)
#endif
#ifndef MYNEWT_VAL_OS_COREDUMP
#define MYNEWT_VAL_OS_COREDUMP (0)
#endif
/* Overridden by hw/bsp/nrf52840pdk (defined by kernel/os) */
#ifndef MYNEWT_VAL_OS_CPUTIME_FREQ
#define MYNEWT_VAL_OS_CPUTIME_FREQ (32768)
#endif
/* Overridden by hw/bsp/nrf52840pdk (defined by kernel/os) */
#ifndef MYNEWT_VAL_OS_CPUTIME_TIMER_NUM
#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (5)
#endif
#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_CHECK
#define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0)
#endif
#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_GUARD
#define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4)
#endif
#ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE
#define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024)
#endif
#ifndef MYNEWT_VAL_OS_MAIN_TASK_PRIO
#define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127)
#endif
#ifndef MYNEWT_VAL_OS_MEMPOOL_CHECK
#define MYNEWT_VAL_OS_MEMPOOL_CHECK (0)
#endif
#ifndef MYNEWT_VAL_OS_MEMPOOL_POISON
#define MYNEWT_VAL_OS_MEMPOOL_POISON (0)
#endif
#ifndef MYNEWT_VAL_OS_SCHEDULING
#define MYNEWT_VAL_OS_SCHEDULING (1)
#endif
#ifndef MYNEWT_VAL_OS_SYSVIEW
#define MYNEWT_VAL_OS_SYSVIEW (0)
#endif
#ifndef MYNEWT_VAL_SANITY_INTERVAL
#define MYNEWT_VAL_SANITY_INTERVAL (15000)
#endif
#ifndef MYNEWT_VAL_WATCHDOG_INTERVAL
#define MYNEWT_VAL_WATCHDOG_INTERVAL (30000)
#endif
/*** libc/baselibc */
#ifndef MYNEWT_VAL_BASELIBC_ASSERT_FILE_LINE
#define MYNEWT_VAL_BASELIBC_ASSERT_FILE_LINE (0)
#endif
#ifndef MYNEWT_VAL_BASELIBC_PRESENT
#define MYNEWT_VAL_BASELIBC_PRESENT (1)
#endif
/*** net/nimble */
#ifndef MYNEWT_VAL_BLE_EXT_ADV
#define MYNEWT_VAL_BLE_EXT_ADV (0)
#endif
#ifndef MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
#endif
#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
#endif
#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
#endif
#ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER
#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1)
#endif
#ifndef MYNEWT_VAL_BLE_ROLE_CENTRAL
#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1)
#endif
#ifndef MYNEWT_VAL_BLE_ROLE_OBSERVER
#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1)
#endif
#ifndef MYNEWT_VAL_BLE_ROLE_PERIPHERAL
#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1)
#endif
#ifndef MYNEWT_VAL_BLE_WHITELIST
#define MYNEWT_VAL_BLE_WHITELIST (1)
#endif
/*** net/nimble/controller */
#ifndef MYNEWT_VAL_BLE_DEVICE
#define MYNEWT_VAL_BLE_DEVICE (1)
#endif
/* Overridden by net/nimble/controller (defined by net/nimble/controller) */
#ifndef MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE
#define MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS
#define MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ (1)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT (1)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_EXT_SCAN_FILT
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_EXT_SCAN_FILT (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY (0)
#endif
/* Overridden by net/nimble/controller (defined by net/nimble/controller) */
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 (1)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION (1)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_PING
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_PING (MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV (MYNEWT_VAL_BLE_EXT_ADV)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (1)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG (1)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES
#define MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES (27)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET
#define MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS
#define MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS (4)
#endif
/* Overridden by net/nimble/controller (defined by net/nimble/controller) */
#ifndef MYNEWT_VAL_BLE_LL_EXT_ADV_AUX_PTR_CNT
#define MYNEWT_VAL_BLE_LL_EXT_ADV_AUX_PTR_CNT (5)
#endif
#ifndef MYNEWT_VAL_BLE_LL_MASTER_SCA
#define MYNEWT_VAL_BLE_LL_MASTER_SCA (4)
#endif
#ifndef MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE
#define MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE (251)
#endif
#ifndef MYNEWT_VAL_BLE_LL_MFRG_ID
#define MYNEWT_VAL_BLE_LL_MFRG_ID (0xFFFF)
#endif
#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS
#define MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS (8)
#endif
#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS
#define MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS (8)
#endif
#ifndef MYNEWT_VAL_BLE_LL_OUR_SCA
#define MYNEWT_VAL_BLE_LL_OUR_SCA (60)
#endif
#ifndef MYNEWT_VAL_BLE_LL_PRIO
#define MYNEWT_VAL_BLE_LL_PRIO (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE
#define MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE (4)
#endif
#ifndef MYNEWT_VAL_BLE_LL_RNG_BUFSIZE
#define MYNEWT_VAL_BLE_LL_RNG_BUFSIZE (32)
#endif
#ifndef MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING
#define MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES
#define MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE)
#endif
#ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES
#define MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE)
#endif
#ifndef MYNEWT_VAL_BLE_LL_TX_PWR_DBM
#define MYNEWT_VAL_BLE_LL_TX_PWR_DBM (0)
#endif
#ifndef MYNEWT_VAL_BLE_LL_USECS_PER_PERIOD
#define MYNEWT_VAL_BLE_LL_USECS_PER_PERIOD (3250)
#endif
#ifndef MYNEWT_VAL_BLE_LL_WHITELIST_SIZE
#define MYNEWT_VAL_BLE_LL_WHITELIST_SIZE (8)
#endif
#ifndef MYNEWT_VAL_BLE_LP_CLOCK
#define MYNEWT_VAL_BLE_LP_CLOCK (1)
#endif
#ifndef MYNEWT_VAL_BLE_NUM_COMP_PKT_RATE
#define MYNEWT_VAL_BLE_NUM_COMP_PKT_RATE (((2000 * OS_TICKS_PER_SEC) / 1000))
#endif
#ifndef MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR
#define MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR ((uint8_t[6]){0xff, 0xaa, 0xff, 0xc0, 0xde, 0xc0})
#endif
/* Overridden by hw/bsp/nrf52840pdk (defined by net/nimble/controller) */
#ifndef MYNEWT_VAL_BLE_XTAL_SETTLE_TIME
#define MYNEWT_VAL_BLE_XTAL_SETTLE_TIME (1500)
#endif
/*** net/nimble/host */
#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO
#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE
#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_INDICATE
#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES
#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY
#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE
#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO
#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ
#define MYNEWT_VAL_BLE_ATT_SVR_READ (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB
#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE
#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT
#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE
#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE
#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1)
#endif
#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS
#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS
#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS
#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID
#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID
#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS
#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_INDICATE
#define MYNEWT_VAL_BLE_GATT_INDICATE (1)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_MAX_PROCS
#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY
#define MYNEWT_VAL_BLE_GATT_NOTIFY (1)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ
#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_LONG
#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS
#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT
#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_RESUME_RATE
#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_SIGNED_WRITE
#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_WRITE
#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_LONG
#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS
#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP
#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE
#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
#endif
#ifndef MYNEWT_VAL_BLE_HOST
#define MYNEWT_VAL_BLE_HOST (1)
#endif
#ifndef MYNEWT_VAL_BLE_HS_DEBUG
#define MYNEWT_VAL_BLE_HS_DEBUG (0)
#endif
#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS
#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0)
#endif
#ifndef MYNEWT_VAL_BLE_HS_REQUIRE_OS
#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1)
#endif
#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM
#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0)
#endif
#ifndef MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS
#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1)
#endif
#ifndef MYNEWT_VAL_BLE_L2CAP_MAX_CHANS
#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS)
#endif
#ifndef MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT
#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000)
#endif
#ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS
#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1)
#endif
/* Overridden by apps/bleall (defined by net/nimble/host) */
#ifndef MYNEWT_VAL_BLE_MESH
#define MYNEWT_VAL_BLE_MESH (1)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE
#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT
#define MYNEWT_VAL_BLE_MONITOR_RTT (0)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED
#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME
#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("monitor")
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE
#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_UART
#define MYNEWT_VAL_BLE_MONITOR_UART (0)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE
#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE
#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64)
#endif
#ifndef MYNEWT_VAL_BLE_MONITOR_UART_DEV
#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0")
#endif
#ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT
#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300)
#endif
#ifndef MYNEWT_VAL_BLE_SM_BONDING
#define MYNEWT_VAL_BLE_SM_BONDING (0)
#endif
#ifndef MYNEWT_VAL_BLE_SM_IO_CAP
#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT)
#endif
#ifndef MYNEWT_VAL_BLE_SM_KEYPRESS
#define MYNEWT_VAL_BLE_SM_KEYPRESS (0)
#endif
#ifndef MYNEWT_VAL_BLE_SM_LEGACY
#define MYNEWT_VAL_BLE_SM_LEGACY (1)
#endif
#ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS
#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1)
#endif
#ifndef MYNEWT_VAL_BLE_SM_MITM
#define MYNEWT_VAL_BLE_SM_MITM (0)
#endif
#ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG
#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0)
#endif
#ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST
#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0)
#endif
/* Overridden by net/nimble/host (defined by net/nimble/host) */
#ifndef MYNEWT_VAL_BLE_SM_SC
#define MYNEWT_VAL_BLE_SM_SC (1)
#endif
#ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST
#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0)
#endif
#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS
#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3)
#endif
#ifndef MYNEWT_VAL_BLE_STORE_MAX_CCCDS
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
#endif
/*** net/nimble/host/mesh */
#ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT
#define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (10)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO
#define MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO (9)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT
#define MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_CRPL
#define MYNEWT_VAL_BLE_MESH_CRPL (10)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG
#define MYNEWT_VAL_BLE_MESH_DEBUG (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_ACCESS
#define MYNEWT_VAL_BLE_MESH_DEBUG_ACCESS (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_ADV
#define MYNEWT_VAL_BLE_MESH_DEBUG_ADV (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_BEACON
#define MYNEWT_VAL_BLE_MESH_DEBUG_BEACON (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_CRYPTO
#define MYNEWT_VAL_BLE_MESH_DEBUG_CRYPTO (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_FRIEND
#define MYNEWT_VAL_BLE_MESH_DEBUG_FRIEND (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_LOW_POWER
#define MYNEWT_VAL_BLE_MESH_DEBUG_LOW_POWER (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_MODEL
#define MYNEWT_VAL_BLE_MESH_DEBUG_MODEL (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_NET
#define MYNEWT_VAL_BLE_MESH_DEBUG_NET (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_PROV
#define MYNEWT_VAL_BLE_MESH_DEBUG_PROV (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_PROXY
#define MYNEWT_VAL_BLE_MESH_DEBUG_PROXY (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_TRANS
#define MYNEWT_VAL_BLE_MESH_DEBUG_TRANS (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_DEV_UUID
#define MYNEWT_VAL_BLE_MESH_DEV_UUID (((uint8_t[16]){0x11, 0x22, 0}))
#endif
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND
#define MYNEWT_VAL_BLE_MESH_FRIEND (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_LPN_COUNT
#define MYNEWT_VAL_BLE_MESH_FRIEND_LPN_COUNT (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_QUEUE_SIZE
#define MYNEWT_VAL_BLE_MESH_FRIEND_QUEUE_SIZE (16)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_RECV_WIN
#define MYNEWT_VAL_BLE_MESH_FRIEND_RECV_WIN (255)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_SUB_LIST_SIZE
#define MYNEWT_VAL_BLE_MESH_FRIEND_SUB_LIST_SIZE (16)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY
#define MYNEWT_VAL_BLE_MESH_GATT_PROXY (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST
#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LABEL_COUNT
#define MYNEWT_VAL_BLE_MESH_LABEL_COUNT (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER
#define MYNEWT_VAL_BLE_MESH_LOW_POWER (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LPN_GROUPS
#define MYNEWT_VAL_BLE_MESH_LPN_GROUPS (10)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LPN_MIN_QUEUE_SIZE
#define MYNEWT_VAL_BLE_MESH_LPN_MIN_QUEUE_SIZE (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT
#define MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT (100)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LPN_RECV_DELAY
#define MYNEWT_VAL_BLE_MESH_LPN_RECV_DELAY (20)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LPN_RECV_WIN_FACTOR
#define MYNEWT_VAL_BLE_MESH_LPN_RECV_WIN_FACTOR (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LPN_RSSI_FACTOR
#define MYNEWT_VAL_BLE_MESH_LPN_RSSI_FACTOR (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY
#define MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY (10)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT
#define MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_MODEL_KEY_COUNT
#define MYNEWT_VAL_BLE_MESH_MODEL_KEY_COUNT (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE
#define MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE (10)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV
#define MYNEWT_VAL_BLE_MESH_PB_ADV (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_PB_GATT
#define MYNEWT_VAL_BLE_MESH_PB_GATT (1)
#endif
/* Overridden by net/nimble/host/mesh (defined by net/nimble/host/mesh) */
#ifndef MYNEWT_VAL_BLE_MESH_PROV
#define MYNEWT_VAL_BLE_MESH_PROV (1)
#endif
/* Overridden by net/nimble/host/mesh (defined by net/nimble/host/mesh) */
#ifndef MYNEWT_VAL_BLE_MESH_PROXY
#define MYNEWT_VAL_BLE_MESH_PROXY (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE
#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_RELAY
#define MYNEWT_VAL_BLE_MESH_RELAY (0)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_RX_SDU_MAX
#define MYNEWT_VAL_BLE_MESH_RX_SDU_MAX (384)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT
#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (2)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_SUBNET_COUNT
#define MYNEWT_VAL_BLE_MESH_SUBNET_COUNT (1)
#endif
#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT
#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4)
#endif
/*** net/nimble/host/services/ans */
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
#endif
#ifndef MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT
#define MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT (0)
#endif
/*** net/nimble/transport/ram */
#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT
#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (4)
#endif
#ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE
#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255)
#endif
#ifndef MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE
#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70)
#endif
#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (2)
#endif
#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT
#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (8)
#endif
/*** sys/console/stub */
#ifndef MYNEWT_VAL_CONSOLE_UART_BAUD
#define MYNEWT_VAL_CONSOLE_UART_BAUD (115200)
#endif
#ifndef MYNEWT_VAL_CONSOLE_UART_DEV
#define MYNEWT_VAL_CONSOLE_UART_DEV ("uart0")
#endif
#ifndef MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL
#define MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL (UART_FLOW_CTL_NONE)
#endif
/*** sys/flash_map */
#ifndef MYNEWT_VAL_FLASH_MAP_MAX_AREAS
#define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10)
#endif
/*** sys/log/stub */
#ifndef MYNEWT_VAL_LOG_CONSOLE
#define MYNEWT_VAL_LOG_CONSOLE (1)
#endif
#ifndef MYNEWT_VAL_LOG_FCB
#define MYNEWT_VAL_LOG_FCB (0)
#endif
#ifndef MYNEWT_VAL_LOG_LEVEL
#define MYNEWT_VAL_LOG_LEVEL (255)
#endif
/*** sys/sysinit */
#ifndef MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT
#define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1)
#endif
#ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE
#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0)
#endif
#ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE
#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0)
#endif
#endif
@@ -0,0 +1,35 @@
/* Linker script to configure memory regions. */
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
MEMORY
{
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x80000
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
}
SECTIONS
{
.vector_relocation :
{
. = ALIGN(256);
__vector_tbl_reloc__ = .;
. = . + (__isr_vector_end - __isr_vector_start);
. = ALIGN(256);
} > RAM
.fs_data :
{
PROVIDE(__start_fs_data = .);
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
} > RAM
.pwr_mgmt_data :
{
PROVIDE(__start_pwr_mgmt_data = .);
KEEP(*(.pwr_mgmt_data))
PROVIDE(__stop_pwr_mgmt_data = .);
} > RAM
} INSERT AFTER .data;
INCLUDE "nrf5x_common.ld"
+175
View File
@@ -0,0 +1,175 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "bsp.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "nimble_port.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/ias/ble_svc_ias.h"
#if LEDS_NUMBER < 4
#error "Board is not equipped with enough amount of LEDs"
#endif
static const char gap_name[] = "freertos";
static TaskHandle_t task_h;
static TimerHandle_t led_tmr_h;
static void start_advertise(void);
static int
ias_event_cb(uint8_t alert_level)
{
switch (alert_level) {
case BLE_SVC_IAS_ALERT_LEVEL_NO_ALERT:
xTimerStop(led_tmr_h, portMAX_DELAY);
bsp_board_leds_off();
break;
case BLE_SVC_IAS_ALERT_LEVEL_MILD_ALERT:
bsp_board_led_on(BSP_BOARD_LED_0);
bsp_board_led_off(BSP_BOARD_LED_1);
bsp_board_led_off(BSP_BOARD_LED_2);
bsp_board_led_on(BSP_BOARD_LED_3);
xTimerStart(led_tmr_h, portMAX_DELAY);
break;
case BLE_SVC_IAS_ALERT_LEVEL_HIGH_ALERT:
bsp_board_leds_on();
xTimerStart(led_tmr_h, portMAX_DELAY);
break;
}
return 0;
}
static void
put_ad(uint8_t ad_type, uint8_t ad_len, const void *ad, uint8_t *buf,
uint8_t *len)
{
buf[(*len)++] = ad_len + 1;
buf[(*len)++] = ad_type;
memcpy(&buf[*len], ad, ad_len);
*len += ad_len;
}
static void
update_ad(void)
{
uint8_t ad[BLE_HS_ADV_MAX_SZ];
uint8_t ad_len = 0;
uint8_t ad_flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
uint16_t ad_uuid = htole16(BLE_SVC_IAS_UUID16);
put_ad(BLE_HS_ADV_TYPE_FLAGS, 1, &ad_flags, ad, &ad_len);
put_ad(BLE_HS_ADV_TYPE_COMP_NAME, sizeof(gap_name), gap_name, ad, &ad_len);
put_ad(BLE_HS_ADV_TYPE_COMP_UUIDS16, sizeof(ad_uuid), &ad_uuid, ad, &ad_len);
ble_gap_adv_set_data(ad, ad_len);
}
static int
gap_event_cb(struct ble_gap_event *event, void *arg)
{
switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
if (event->connect.status) {
start_advertise();
}
break;
case BLE_GAP_EVENT_DISCONNECT:
start_advertise();
break;
}
return 0;
}
static void
start_advertise(void)
{
struct ble_gap_adv_params advp;
int rc;
update_ad();
memset(&advp, 0, sizeof advp);
advp.conn_mode = BLE_GAP_CONN_MODE_UND;
advp.disc_mode = BLE_GAP_DISC_MODE_GEN;
rc = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER,
&advp, gap_event_cb, NULL);
assert(rc == 0);
}
static void
on_sync_cb(void)
{
start_advertise();
}
static void
task_func(void *param)
{
int rc;
rc = hal_timer_init(0, NULL);
assert(rc == 0);
rc = hal_timer_init(5, NULL);
assert(rc == 0);
rc = os_cputime_init(MYNEWT_VAL(OS_CPUTIME_FREQ));
assert(rc == 0);
nimble_init();
ble_hs_cfg.sync_cb = on_sync_cb;
ble_svc_gap_device_name_set(gap_name);
ble_svc_ias_set_cb(ias_event_cb);
nimble_run();
}
static void led_tmr_func(void *param)
{
bsp_board_led_invert(BSP_BOARD_LED_0);
bsp_board_led_invert(BSP_BOARD_LED_1);
bsp_board_led_invert(BSP_BOARD_LED_2);
bsp_board_led_invert(BSP_BOARD_LED_3);
}
void start_nimble(void)
{
void ble_ll_task(void *arg);
led_tmr_h = xTimerCreate("led", 500, pdTRUE, NULL, led_tmr_func);
xTaskCreate(task_func, "nimble", configMINIMAL_STACK_SIZE + 400,
NULL, 2, &task_h);
xTaskCreate(ble_ll_task, "ll", configMINIMAL_STACK_SIZE + 100,
NULL, 0, &task_h);
}
@@ -0,0 +1,73 @@
/* mbed Microcontroller Library - cmsis_nvic for XXXX
* Copyright (c) 2009-2011 ARM Limited. All rights reserved.
*
* CMSIS-style functionality to support dynamic vectors
*/
#include "bsp/cmsis_nvic.h"
#ifndef __CORTEX_M
#error "Macro __CORTEX_M not defined; must define cortex-m type!"
#endif
#if (__CORTEX_M == 0)
#ifndef __VTOR_PRESENT
/* no VTOR is defined so we assume we can't relocate the vector table */
#define __VTOR_PRESENT (0)
#endif
#endif
extern char __isr_vector[];
extern char __vector_tbl_reloc__[];
void
NVIC_Relocate(void)
{
uint32_t *current_location;
uint32_t *new_location;
int i;
/*
* Relocate the vector table from its current position to the position
* designated in the linker script.
*/
current_location = (uint32_t *)&__isr_vector;
new_location = (uint32_t *)&__vector_tbl_reloc__;
if (new_location != current_location) {
for (i = 0; i < NVIC_NUM_VECTORS; i++) {
new_location[i] = current_location[i];
}
}
/* Set VTOR except for M0 */
#if ((__CORTEX_M == 0) && (__VTOR_PRESENT == 0))
#else
SCB->VTOR = (uint32_t)&__vector_tbl_reloc__;
#endif
}
void
NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
{
uint32_t *vectors;
#if ((__CORTEX_M == 0) && (__VTOR_PRESENT == 0))
vectors = (uint32_t *)&__vector_tbl_reloc__;
#else
vectors = (uint32_t *)SCB->VTOR;
#endif
vectors[IRQn + NVIC_USER_IRQ_OFFSET] = vector;
__DMB();
}
uint32_t
NVIC_GetVector(IRQn_Type IRQn)
{
uint32_t *vectors;
#if (__CORTEX_M == 0)
vectors = (uint32_t *)&__vector_tbl_reloc__;
#else
vectors = (uint32_t*)SCB->VTOR;
#endif
return vectors[IRQn + NVIC_USER_IRQ_OFFSET];
}
+932
View File
@@ -0,0 +1,932 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <stdint.h>
#include <assert.h>
#include <errno.h>
#include "syscfg/syscfg.h"
#include "bsp/cmsis_nvic.h"
#include "hal/hal_timer.h"
#include "os/os_trace_api.h"
#include "nrf.h"
#include "mcu/nrf52_hal.h"
/* IRQ prototype */
typedef void (*hal_timer_irq_handler_t)(void);
/* User CC 2 for reading counter, CC 3 for timer isr */
#define NRF_TIMER_CC_READ (2)
#define NRF_TIMER_CC_INT (3)
/* Output compare 2 used for RTC timers */
#define NRF_RTC_TIMER_CC_INT (2)
/* Maximum number of hal timers used */
#define NRF52_HAL_TIMER_MAX (6)
/* Maximum timer frequency */
#define NRF52_MAX_TIMER_FREQ (16000000)
struct nrf52_hal_timer {
uint8_t tmr_enabled;
uint8_t tmr_irq_num;
uint8_t tmr_rtc;
uint8_t tmr_pad;
uint32_t tmr_cntr;
uint32_t timer_isrs;
uint32_t tmr_freq;
void *tmr_reg;
TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
};
#if MYNEWT_VAL(TIMER_0)
struct nrf52_hal_timer nrf52_hal_timer0;
#endif
#if MYNEWT_VAL(TIMER_1)
struct nrf52_hal_timer nrf52_hal_timer1;
#endif
#if MYNEWT_VAL(TIMER_2)
struct nrf52_hal_timer nrf52_hal_timer2;
#endif
#if MYNEWT_VAL(TIMER_3)
struct nrf52_hal_timer nrf52_hal_timer3;
#endif
#if MYNEWT_VAL(TIMER_4)
struct nrf52_hal_timer nrf52_hal_timer4;
#endif
#if MYNEWT_VAL(TIMER_5)
struct nrf52_hal_timer nrf52_hal_timer5;
#endif
static const struct nrf52_hal_timer *nrf52_hal_timers[NRF52_HAL_TIMER_MAX] = {
#if MYNEWT_VAL(TIMER_0)
&nrf52_hal_timer0,
#else
NULL,
#endif
#if MYNEWT_VAL(TIMER_1)
&nrf52_hal_timer1,
#else
NULL,
#endif
#if MYNEWT_VAL(TIMER_2)
&nrf52_hal_timer2,
#else
NULL,
#endif
#if MYNEWT_VAL(TIMER_3)
&nrf52_hal_timer3,
#else
NULL,
#endif
#if MYNEWT_VAL(TIMER_4)
&nrf52_hal_timer4,
#else
NULL,
#endif
#if MYNEWT_VAL(TIMER_5)
&nrf52_hal_timer5
#else
NULL
#endif
};
/* Resolve timer number into timer structure */
#define NRF52_HAL_TIMER_RESOLVE(__n, __v) \
if ((__n) >= NRF52_HAL_TIMER_MAX) { \
rc = EINVAL; \
goto err; \
} \
(__v) = (struct nrf52_hal_timer *) nrf52_hal_timers[(__n)]; \
if ((__v) == NULL) { \
rc = EINVAL; \
goto err; \
}
/* Interrupt mask for interrupt enable/clear */
#define NRF_TIMER_INT_MASK(x) ((1 << (uint32_t)(x)) << 16)
static uint32_t
nrf_read_timer_cntr(NRF_TIMER_Type *hwtimer)
{
uint32_t tcntr;
/* Force a capture of the timer into 'cntr' capture channel; read it */
hwtimer->TASKS_CAPTURE[NRF_TIMER_CC_READ] = 1;
tcntr = hwtimer->CC[NRF_TIMER_CC_READ];
return tcntr;
}
/**
* nrf timer set ocmp
*
* Set the OCMP used by the timer to the desired expiration tick
*
* NOTE: Must be called with interrupts disabled.
*
* @param timer Pointer to timer.
*/
static void
nrf_timer_set_ocmp(struct nrf52_hal_timer *bsptimer, uint32_t expiry)
{
int32_t delta_t;
uint32_t temp;
uint32_t cntr;
NRF_TIMER_Type *hwtimer;
NRF_RTC_Type *rtctimer;
if (bsptimer->tmr_rtc) {
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
temp = bsptimer->tmr_cntr;
cntr = rtctimer->COUNTER;
if (rtctimer->EVENTS_OVRFLW) {
temp += (1UL << 24);
cntr = rtctimer->COUNTER;
}
temp |= cntr;
delta_t = (int32_t)(expiry - temp);
/*
* The nrf documentation states that you must set the output
* compare to 2 greater than the counter to guarantee an interrupt.
* Since the counter can tick once while we check, we make sure
* it is greater than 2.
*/
if (delta_t < 3) {
NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
} else {
if (delta_t < (1UL << 24)) {
rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry & 0x00ffffff;
} else {
/* CC too far ahead. Just make sure we set compare far ahead */
rtctimer->CC[NRF_RTC_TIMER_CC_INT] = cntr + (1UL << 23);
}
rtctimer->INTENSET = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
}
} else {
hwtimer = bsptimer->tmr_reg;
/* Disable ocmp interrupt and set new value */
hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
/* Set output compare register to timer expiration */
hwtimer->CC[NRF_TIMER_CC_INT] = expiry;
/* Clear interrupt flag */
hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
/* Enable the output compare interrupt */
hwtimer->INTENSET = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
/* Force interrupt to occur as we may have missed it */
if ((int32_t)(nrf_read_timer_cntr(hwtimer) - expiry) >= 0) {
NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
}
}
}
/* Disable output compare used for timer */
static void
nrf_timer_disable_ocmp(NRF_TIMER_Type *hwtimer)
{
hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
}
static void
nrf_rtc_disable_ocmp(NRF_RTC_Type *rtctimer)
{
rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
}
static uint32_t
hal_timer_read_bsptimer(struct nrf52_hal_timer *bsptimer)
{
uint32_t low32;
uint32_t ctx;
uint32_t tcntr;
NRF_RTC_Type *rtctimer;
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
__HAL_DISABLE_INTERRUPTS(ctx);
tcntr = bsptimer->tmr_cntr;
low32 = rtctimer->COUNTER;
if (rtctimer->EVENTS_OVRFLW) {
tcntr += (1UL << 24);
bsptimer->tmr_cntr = tcntr;
low32 = rtctimer->COUNTER;
rtctimer->EVENTS_OVRFLW = 0;
NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
}
tcntr |= low32;
__HAL_ENABLE_INTERRUPTS(ctx);
return tcntr;
}
#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \
MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4) || MYNEWT_VAL(TIMER_5))
/**
* hal timer chk queue
*
*
* @param bsptimer
*/
static void
hal_timer_chk_queue(struct nrf52_hal_timer *bsptimer)
{
int32_t delta;
uint32_t tcntr;
uint32_t ctx;
struct hal_timer *timer;
/* disable interrupts */
__HAL_DISABLE_INTERRUPTS(ctx);
while ((timer = TAILQ_FIRST(&bsptimer->hal_timer_q)) != NULL) {
if (bsptimer->tmr_rtc) {
tcntr = hal_timer_read_bsptimer(bsptimer);
/*
* If we are within 3 ticks of RTC, we wont be able to set compare.
* Thus, we have to service this timer early.
*/
delta = -3;
} else {
tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
delta = 0;
}
if ((int32_t)(tcntr - timer->expiry) >= delta) {
TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
timer->link.tqe_prev = NULL;
timer->cb_func(timer->cb_arg);
} else {
break;
}
}
/* Any timers left on queue? If so, we need to set OCMP */
timer = TAILQ_FIRST(&bsptimer->hal_timer_q);
if (timer) {
nrf_timer_set_ocmp(bsptimer, timer->expiry);
} else {
if (bsptimer->tmr_rtc) {
nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg);
} else {
nrf_timer_disable_ocmp(bsptimer->tmr_reg);
}
}
__HAL_ENABLE_INTERRUPTS(ctx);
}
#endif
/**
* hal timer irq handler
*
* Generic HAL timer irq handler.
*
* @param tmr
*/
/**
* hal timer irq handler
*
* This is the global timer interrupt routine.
*
*/
#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \
MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4))
static void
hal_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
{
uint32_t compare;
NRF_TIMER_Type *hwtimer;
os_trace_enter_isr();
/* Check interrupt source. If set, clear them */
hwtimer = bsptimer->tmr_reg;
compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
if (compare) {
hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
}
/* XXX: make these stats? */
/* Count # of timer isrs */
++bsptimer->timer_isrs;
/*
* NOTE: we dont check the 'compare' variable here due to how the timer
* is implemented on this chip. There is no way to force an output
* compare, so if we are late setting the output compare (i.e. the timer
* counter is already passed the output compare value), we use the NVIC
* to set a pending interrupt. This means that there will be no compare
* flag set, so all we do is check to see if the compare interrupt is
* enabled.
*/
if (hwtimer->INTENCLR & NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT)) {
hal_timer_chk_queue(bsptimer);
/* XXX: Recommended by nordic to make sure interrupts are cleared */
compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
}
os_trace_exit_isr();
}
#endif
#if MYNEWT_VAL(TIMER_5)
static void
hal_rtc_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
{
uint32_t overflow;
uint32_t compare;
NRF_RTC_Type *rtctimer;
/* Check interrupt source. If set, clear them */
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
if (compare) {
rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT] = 0;
}
overflow = rtctimer->EVENTS_OVRFLW;
if (overflow) {
rtctimer->EVENTS_OVRFLW = 0;
bsptimer->tmr_cntr += (1UL << 24);
}
/* Count # of timer isrs */
++bsptimer->timer_isrs;
/*
* NOTE: we dont check the 'compare' variable here due to how the timer
* is implemented on this chip. There is no way to force an output
* compare, so if we are late setting the output compare (i.e. the timer
* counter is already passed the output compare value), we use the NVIC
* to set a pending interrupt. This means that there will be no compare
* flag set, so all we do is check to see if the compare interrupt is
* enabled.
*/
hal_timer_chk_queue(bsptimer);
/* Recommended by nordic to make sure interrupts are cleared */
compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
}
#endif
#if MYNEWT_VAL(TIMER_0)
void
nrf52_timer0_irq_handler(void)
{
hal_timer_irq_handler(&nrf52_hal_timer0);
}
#endif
#if MYNEWT_VAL(TIMER_1)
void
nrf52_timer1_irq_handler(void)
{
hal_timer_irq_handler(&nrf52_hal_timer1);
}
#endif
#if MYNEWT_VAL(TIMER_2)
void
nrf52_timer2_irq_handler(void)
{
hal_timer_irq_handler(&nrf52_hal_timer2);
}
#endif
#if MYNEWT_VAL(TIMER_3)
void
nrf52_timer3_irq_handler(void)
{
hal_timer_irq_handler(&nrf52_hal_timer3);
}
#endif
#if MYNEWT_VAL(TIMER_4)
void
nrf52_timer4_irq_handler(void)
{
hal_timer_irq_handler(&nrf52_hal_timer4);
}
#endif
#if MYNEWT_VAL(TIMER_5)
void
nrf52_timer5_irq_handler(void)
{
hal_rtc_timer_irq_handler(&nrf52_hal_timer5);
}
#endif
/**
* hal timer init
*
* Initialize platform specific timer items
*
* @param timer_num Timer number to initialize
* @param cfg Pointer to platform specific configuration
*
* @return int 0: success; error code otherwise
*/
int
hal_timer_init(int timer_num, void *cfg)
{
int rc;
uint8_t irq_num;
struct nrf52_hal_timer *bsptimer;
void *hwtimer;
hal_timer_irq_handler_t irq_isr;
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
/* If timer is enabled do not allow init */
if (bsptimer->tmr_enabled) {
rc = EINVAL;
goto err;
}
switch (timer_num) {
#if MYNEWT_VAL(TIMER_0)
case 0:
irq_num = TIMER0_IRQn;
hwtimer = NRF_TIMER0;
irq_isr = nrf52_timer0_irq_handler;
break;
#endif
#if MYNEWT_VAL(TIMER_1)
case 1:
irq_num = TIMER1_IRQn;
hwtimer = NRF_TIMER1;
irq_isr = nrf52_timer1_irq_handler;
break;
#endif
#if MYNEWT_VAL(TIMER_2)
case 2:
irq_num = TIMER2_IRQn;
hwtimer = NRF_TIMER2;
irq_isr = nrf52_timer2_irq_handler;
break;
#endif
#if MYNEWT_VAL(TIMER_3)
case 3:
irq_num = TIMER3_IRQn;
hwtimer = NRF_TIMER3;
irq_isr = nrf52_timer3_irq_handler;
break;
#endif
#if MYNEWT_VAL(TIMER_4)
case 4:
irq_num = TIMER4_IRQn;
hwtimer = NRF_TIMER4;
irq_isr = nrf52_timer4_irq_handler;
break;
#endif
#if MYNEWT_VAL(TIMER_5)
case 5:
irq_num = RTC0_IRQn;
hwtimer = NRF_RTC0;
irq_isr = nrf52_timer5_irq_handler;
bsptimer->tmr_rtc = 1;
break;
#endif
default:
hwtimer = NULL;
break;
}
if (hwtimer == NULL) {
rc = EINVAL;
goto err;
}
bsptimer->tmr_reg = hwtimer;
bsptimer->tmr_irq_num = irq_num;
/* Disable IRQ, set priority and set vector in table */
NVIC_DisableIRQ(irq_num);
NVIC_SetPriority(irq_num, (1 << __NVIC_PRIO_BITS) - 1);
NVIC_SetVector(irq_num, (uint32_t)irq_isr);
return 0;
err:
return rc;
}
/**
* hal timer config
*
* Configure a timer to run at the desired frequency. This starts the timer.
*
* @param timer_num
* @param freq_hz
*
* @return int
*/
int
hal_timer_config(int timer_num, uint32_t freq_hz)
{
int rc;
uint8_t prescaler;
uint32_t ctx;
uint32_t div;
uint32_t min_delta;
uint32_t max_delta;
struct nrf52_hal_timer *bsptimer;
NRF_TIMER_Type *hwtimer;
#if MYNEWT_VAL(TIMER_5)
NRF_RTC_Type *rtctimer;
#endif
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
#if MYNEWT_VAL(TIMER_5)
if (timer_num == 5) {
/* NOTE: we only allow the RTC frequency to be set at 32768 */
if (bsptimer->tmr_enabled || (freq_hz != 32768) ||
(bsptimer->tmr_reg == NULL)) {
rc = EINVAL;
goto err;
}
bsptimer->tmr_freq = freq_hz;
bsptimer->tmr_enabled = 1;
__HAL_DISABLE_INTERRUPTS(ctx);
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
/* Stop the timer first */
rtctimer->TASKS_STOP = 1;
/* Always no prescaler */
rtctimer->PRESCALER = 0;
/* Clear overflow events and set overflow interrupt */
rtctimer->EVENTS_OVRFLW = 0;
rtctimer->INTENSET = RTC_INTENSET_OVRFLW_Msk;
/* Start the timer */
rtctimer->TASKS_START = 1;
/* Set isr in vector table and enable interrupt */
NVIC_EnableIRQ(bsptimer->tmr_irq_num);
__HAL_ENABLE_INTERRUPTS(ctx);
return 0;
}
#endif
/* Set timer to desired frequency */
div = NRF52_MAX_TIMER_FREQ / freq_hz;
/*
* Largest prescaler is 2^9 and must make sure frequency not too high.
* If hwtimer is NULL it means that the timer was not initialized prior
* to call.
*/
if (bsptimer->tmr_enabled || (div == 0) || (div > 512) ||
(bsptimer->tmr_reg == NULL)) {
rc = EINVAL;
goto err;
}
if (div == 1) {
prescaler = 0;
} else {
/* Find closest prescaler */
for (prescaler = 1; prescaler < 10; ++prescaler) {
if (div <= (1 << prescaler)) {
min_delta = div - (1 << (prescaler - 1));
max_delta = (1 << prescaler) - div;
if (min_delta < max_delta) {
prescaler -= 1;
}
break;
}
}
}
/* Now set the actual frequency */
bsptimer->tmr_freq = NRF52_MAX_TIMER_FREQ / (1 << prescaler);
bsptimer->tmr_enabled = 1;
/* disable interrupts */
__HAL_DISABLE_INTERRUPTS(ctx);
/* Make sure HFXO is started */
if ((NRF_CLOCK->HFCLKSTAT &
(CLOCK_HFCLKSTAT_SRC_Msk | CLOCK_HFCLKSTAT_STATE_Msk)) !=
(CLOCK_HFCLKSTAT_SRC_Msk | CLOCK_HFCLKSTAT_STATE_Msk)) {
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (1) {
if ((NRF_CLOCK->EVENTS_HFCLKSTARTED) != 0) {
break;
}
}
}
hwtimer = bsptimer->tmr_reg;
/* Stop the timer first */
hwtimer->TASKS_STOP = 1;
/* Put the timer in timer mode using 32 bits. */
hwtimer->MODE = TIMER_MODE_MODE_Timer;
hwtimer->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
/* Set the pre-scalar */
hwtimer->PRESCALER = prescaler;
/* Start the timer */
hwtimer->TASKS_START = 1;
NVIC_EnableIRQ(bsptimer->tmr_irq_num);
__HAL_ENABLE_INTERRUPTS(ctx);
return 0;
err:
return rc;
}
/**
* hal timer deinit
*
* De-initialize a HW timer.
*
* @param timer_num
*
* @return int
*/
int
hal_timer_deinit(int timer_num)
{
int rc;
uint32_t ctx;
struct nrf52_hal_timer *bsptimer;
NRF_TIMER_Type *hwtimer;
NRF_RTC_Type *rtctimer;
rc = 0;
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
__HAL_DISABLE_INTERRUPTS(ctx);
if (bsptimer->tmr_rtc) {
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
rtctimer->TASKS_STOP = 1;
} else {
hwtimer = (NRF_TIMER_Type *)bsptimer->tmr_reg;
hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
hwtimer->TASKS_STOP = 1;
}
bsptimer->tmr_enabled = 0;
bsptimer->tmr_reg = NULL;
__HAL_ENABLE_INTERRUPTS(ctx);
err:
return rc;
}
/**
* hal timer get resolution
*
* Get the resolution of the timer. This is the timer period, in nanoseconds
*
* @param timer_num
*
* @return uint32_t The
*/
uint32_t
hal_timer_get_resolution(int timer_num)
{
int rc;
uint32_t resolution;
struct nrf52_hal_timer *bsptimer;
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
resolution = 1000000000 / bsptimer->tmr_freq;
return resolution;
err:
rc = 0;
return rc;
}
/**
* hal timer read
*
* Returns the timer counter. NOTE: if the timer is a 16-bit timer, only
* the lower 16 bits are valid. If the timer is a 64-bit timer, only the
* low 32-bits are returned.
*
* @return uint32_t The timer counter register.
*/
uint32_t
hal_timer_read(int timer_num)
{
int rc;
uint32_t tcntr;
struct nrf52_hal_timer *bsptimer;
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
if (bsptimer->tmr_rtc) {
tcntr = hal_timer_read_bsptimer(bsptimer);
} else {
tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
}
return tcntr;
/* Assert here since there is no invalid return code */
err:
assert(0);
rc = 0;
return rc;
}
/**
* hal timer delay
*
* Blocking delay for n ticks
*
* @param timer_num
* @param ticks
*
* @return int 0 on success; error code otherwise.
*/
int
hal_timer_delay(int timer_num, uint32_t ticks)
{
uint32_t until;
until = hal_timer_read(timer_num) + ticks;
while ((int32_t)(hal_timer_read(timer_num) - until) <= 0) {
/* Loop here till finished */
}
return 0;
}
/**
*
* Initialize the HAL timer structure with the callback and the callback
* argument. Also initializes the HW specific timer pointer.
*
* @param cb_func
*
* @return int
*/
int
hal_timer_set_cb(int timer_num, struct hal_timer *timer, hal_timer_cb cb_func,
void *arg)
{
int rc;
struct nrf52_hal_timer *bsptimer;
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
timer->cb_func = cb_func;
timer->cb_arg = arg;
timer->link.tqe_prev = NULL;
timer->bsp_timer = bsptimer;
rc = 0;
err:
return rc;
}
int
hal_timer_start(struct hal_timer *timer, uint32_t ticks)
{
int rc;
uint32_t tick;
struct nrf52_hal_timer *bsptimer;
/* Set the tick value at which the timer should expire */
bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
if (bsptimer->tmr_rtc) {
tick = hal_timer_read_bsptimer(bsptimer) + ticks;
} else {
tick = nrf_read_timer_cntr(bsptimer->tmr_reg) + ticks;
}
rc = hal_timer_start_at(timer, tick);
return rc;
}
int
hal_timer_start_at(struct hal_timer *timer, uint32_t tick)
{
uint32_t ctx;
struct hal_timer *entry;
struct nrf52_hal_timer *bsptimer;
if ((timer == NULL) || (timer->link.tqe_prev != NULL) ||
(timer->cb_func == NULL)) {
return EINVAL;
}
bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
timer->expiry = tick;
__HAL_DISABLE_INTERRUPTS(ctx);
if (TAILQ_EMPTY(&bsptimer->hal_timer_q)) {
TAILQ_INSERT_HEAD(&bsptimer->hal_timer_q, timer, link);
} else {
TAILQ_FOREACH(entry, &bsptimer->hal_timer_q, link) {
if ((int32_t)(timer->expiry - entry->expiry) < 0) {
TAILQ_INSERT_BEFORE(entry, timer, link);
break;
}
}
if (!entry) {
TAILQ_INSERT_TAIL(&bsptimer->hal_timer_q, timer, link);
}
}
/* If this is the head, we need to set new OCMP */
if (timer == TAILQ_FIRST(&bsptimer->hal_timer_q)) {
nrf_timer_set_ocmp(bsptimer, timer->expiry);
}
__HAL_ENABLE_INTERRUPTS(ctx);
return 0;
}
/**
* hal timer stop
*
* Stop a timer.
*
* @param timer
*
* @return int
*/
int
hal_timer_stop(struct hal_timer *timer)
{
uint32_t ctx;
int reset_ocmp;
struct hal_timer *entry;
struct nrf52_hal_timer *bsptimer;
if (timer == NULL) {
return EINVAL;
}
bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
__HAL_DISABLE_INTERRUPTS(ctx);
if (timer->link.tqe_prev != NULL) {
reset_ocmp = 0;
if (timer == TAILQ_FIRST(&bsptimer->hal_timer_q)) {
/* If first on queue, we will need to reset OCMP */
entry = TAILQ_NEXT(timer, link);
reset_ocmp = 1;
}
TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
timer->link.tqe_prev = NULL;
if (reset_ocmp) {
if (entry) {
nrf_timer_set_ocmp((struct nrf52_hal_timer *)entry->bsp_timer,
entry->expiry);
} else {
if (bsptimer->tmr_rtc) {
nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg);
} else {
nrf_timer_disable_ocmp(bsptimer->tmr_reg);
}
}
}
}
__HAL_ENABLE_INTERRUPTS(ctx);
return 0;
}
+60
View File
@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <stdbool.h>
#include <stdint.h>
#include "FreeRTOS.h"
#include "task.h"
#include "bsp.h"
#include "nordic_common.h"
#include "nrf_drv_clock.h"
#include "sdk_errors.h"
#include "app_error.h"
#include "bsp/cmsis_nvic.h"
int main(void)
{
ret_code_t err_code;
/* Relocate ISR vector from flash to RAM */
NVIC_Relocate();
/* Initialize clock driver for better time accuracy in FREERTOS */
err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);
/* Configure LED-pins as outputs */
bsp_board_leds_init();
bsp_board_leds_off();
/* Activate deep sleep mode */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
void start_nimble(void);
start_nimble();
/* Start FreeRTOS scheduler. */
vTaskStartScheduler();
while (true)
{
/* FreeRTOS should not be here... FreeRTOS goes back to the start of stack
* in vTaskStartScheduler function. */
}
}
+348
View File
@@ -0,0 +1,348 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <assert.h>
#include <stdint.h>
#include <string.h>
#include "os/os.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "timers.h"
static struct os_eventq dflt_evq;
static inline bool in_isr()
{
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
}
int
os_started(void)
{
return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
}
struct os_task *
os_sched_get_current_task(void)
{
return xTaskGetCurrentTaskHandle();
}
os_error_t
os_mutex_init(struct os_mutex *mu)
{
if (!mu) {
return OS_INVALID_PARM;
}
mu->handle = xSemaphoreCreateRecursiveMutex();
assert(mu->handle);
return OS_OK;
}
os_error_t
os_mutex_release(struct os_mutex *mu)
{
if (!mu) {
return OS_INVALID_PARM;
}
assert(mu->handle);
if (in_isr()) {
assert(0);
} else {
if (xSemaphoreGiveRecursive(mu->handle) != pdPASS) {
return OS_BAD_MUTEX;
}
}
return OS_OK;
}
os_error_t
os_mutex_pend(struct os_mutex *mu, uint32_t timeout)
{
if (!mu) {
return OS_INVALID_PARM;
}
assert(mu->handle);
if (in_isr()) {
assert(0);
} else {
if (xSemaphoreTakeRecursive(mu->handle, timeout) != pdPASS) {
return OS_TIMEOUT;
}
}
return OS_OK;
}
os_error_t
os_sem_init(struct os_sem *sem, uint16_t tokens)
{
if (!sem) {
return OS_INVALID_PARM;
}
sem->handle = xSemaphoreCreateCounting(128, tokens);
assert(sem->handle);
return OS_OK;
}
os_error_t
os_sem_release(struct os_sem *sem)
{
BaseType_t ret;
BaseType_t woken;
if (!sem) {
return OS_INVALID_PARM;
}
assert(sem->handle);
if (in_isr()) {
ret = xSemaphoreGiveFromISR(sem->handle, &woken);
assert(ret == pdPASS);
portYIELD_FROM_ISR(woken);
} else {
ret = xSemaphoreGive(sem->handle);
assert(ret == pdPASS);
}
return OS_OK;
}
os_error_t
os_sem_pend(struct os_sem *sem, uint32_t timeout)
{
BaseType_t woken;
if (!sem) {
return OS_INVALID_PARM;
}
assert(sem->handle);
if (in_isr()) {
assert(timeout == 0);
if (xSemaphoreTakeFromISR(sem->handle, &woken) != pdPASS) {
portYIELD_FROM_ISR(woken);
return OS_TIMEOUT;
}
portYIELD_FROM_ISR(woken);
} else {
if (xSemaphoreTake(sem->handle, timeout) != pdPASS) {
return OS_TIMEOUT;
}
}
return OS_OK;
}
uint16_t
os_sem_get_count(struct os_sem *sem)
{
/* XXX FreeRTOS 9.x added dedicated API for this - it's the same as below */
return uxQueueMessagesWaiting(sem->handle);
}
struct os_eventq *
os_eventq_dflt_get(void)
{
if (!dflt_evq.q) {
dflt_evq.q = xQueueCreate(32, sizeof(struct os_event *));
}
return &dflt_evq;
}
void
os_eventq_init(struct os_eventq *evq)
{
evq->q = xQueueCreate(32, sizeof(struct os_event *));
}
struct os_event *
os_eventq_get(struct os_eventq *evq)
{
struct os_event *ev;
BaseType_t ret;
ret = xQueueReceive(evq->q, &ev, portMAX_DELAY);
assert(ret == pdPASS);
ev->ev_queued = 0;
return ev;
}
void
os_eventq_put(struct os_eventq *evq, struct os_event *ev)
{
BaseType_t ret;
if (OS_EVENT_QUEUED(ev)) {
return;
}
ev->ev_queued = 1;
ret = xQueueSendToBack(evq->q, &ev, 0);
assert(ret == pdPASS);
}
void
os_eventq_remove(struct os_eventq *evq, struct os_event *ev)
{
struct os_event *tmp_ev;
BaseType_t ret;
int i;
int count;
if (!OS_EVENT_QUEUED(ev)) {
return;
}
/*
* XXX We cannot extract element from inside FreeRTOS queue so as a quick
* workaround we'll just remove all elements and add them back except the
* one we need to remove. This is silly, but works for now - we probably
* better use counting semaphore with os_queue to handle this in future.
*/
vPortEnterCritical();
count = uxQueueMessagesWaiting(evq->q);
for (i = 0; i < count; i++) {
ret = xQueueReceive(evq->q, &tmp_ev, 0);
assert(ret == pdPASS);
if (tmp_ev == ev) {
continue;
}
ret = xQueueSendToBack(evq->q, &tmp_ev, 0);
assert(ret == pdPASS);
}
vPortExitCritical();
ev->ev_queued = 0;
}
void
os_eventq_run(struct os_eventq *evq)
{
struct os_event *ev;
ev = os_eventq_get(evq);
assert(ev->ev_cb != NULL);
ev->ev_cb(ev);
}
static void
os_callout_timer_cb(TimerHandle_t timer)
{
struct os_callout *c;
c = pvTimerGetTimerID(timer);
assert(c);
if (c->c_evq) {
os_eventq_put(c->c_evq, &c->c_ev);
} else {
c->c_ev.ev_cb(&c->c_ev);
}
}
void
os_callout_init(struct os_callout *c, struct os_eventq *evq,
os_event_fn *ev_cb, void *ev_arg)
{
memset(c, 0, sizeof(*c));
c->c_ev.ev_cb = ev_cb;
c->c_ev.ev_arg = ev_arg;
c->c_evq = evq;
c->c_timer = xTimerCreate("co", 1, pdFALSE, c, os_callout_timer_cb);
}
int
os_callout_reset(struct os_callout *c, int32_t ticks)
{
BaseType_t woken1, woken2, woken3;
if (ticks < 0) {
return OS_EINVAL;
}
if (ticks == 0) {
ticks = 1;
}
c->c_ticks = os_time_get() + ticks;
if (in_isr()) {
xTimerStopFromISR(c->c_timer, &woken1);
xTimerChangePeriodFromISR(c->c_timer, ticks, &woken2);
xTimerResetFromISR(c->c_timer, &woken3);
portYIELD_FROM_ISR(woken1 || woken2 || woken3);
} else {
xTimerStop(c->c_timer, portMAX_DELAY);
xTimerChangePeriod(c->c_timer, ticks, portMAX_DELAY);
xTimerReset(c->c_timer, portMAX_DELAY);
}
return OS_OK;
}
int
os_callout_queued(struct os_callout *c)
{
return xTimerIsTimerActive(c->c_timer) == pdTRUE;
}
void
os_callout_stop(struct os_callout *c)
{
xTimerStop(c->c_timer, portMAX_DELAY);
}
os_time_t
os_time_get(void)
{
return xTaskGetTickCountFromISR();
}
int
os_time_ms_to_ticks(uint32_t ms, uint32_t *out_ticks)
{
*out_ticks = ms;
return OS_OK;
}