Merge branch 'contiki'
Conflicts: cpu/cc26xx-cc13xx/lib/cc13xxware cpu/cc26xx-cc13xx/lib/cc26xxware
This commit is contained in:
commit
2f8549aaae
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -4,9 +4,6 @@
|
|||
[submodule "tools/cc2538-bsl"]
|
||||
path = tools/cc2538-bsl
|
||||
url = https://github.com/JelmerT/cc2538-bsl.git
|
||||
[submodule "cpu/cc26xx-cc13xx/lib/cc26xxware"]
|
||||
path = cpu/cc26xx-cc13xx/lib/cc26xxware
|
||||
url = https://github.com/contiki-os/cc26xxware.git
|
||||
[submodule "cpu/cc26xx-cc13xx/lib/cc13xxware"]
|
||||
path = cpu/cc26xx-cc13xx/lib/cc13xxware
|
||||
url = https://github.com/contiki-os/cc13xxware.git
|
||||
|
@ -14,3 +11,6 @@
|
|||
path = platform/stm32nucleo-spirit1/stm32cube-lib
|
||||
url = https://github.com/STclab/stm32nucleo-spirit1-lib
|
||||
|
||||
[submodule "tools/sensniff"]
|
||||
path = tools/sensniff
|
||||
url = https://github.com/g-oikonomou/sensniff.git
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
# Workaround for the issue found in the stable image promoted on Dec 1, 2016.
|
||||
# See https://github.com/travis-ci/travis-ci/issues/6928#issuecomment-264227708
|
||||
group: deprecated
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
language: c #NOTE: this will set CC=gcc which might cause trouble
|
||||
|
@ -158,3 +162,4 @@ env:
|
|||
- BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja'
|
||||
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja'
|
||||
- BUILD_TYPE='compile-avr' BUILD_CATEGORY='compile' BUILD_ARCH='avr-rss2'
|
||||
- BUILD_TYPE='ieee802154'
|
||||
|
|
|
@ -45,6 +45,14 @@
|
|||
#include "net/ipv6/uip-ds6-route.h"
|
||||
#include "net/packetbuf.h"
|
||||
#include "net/rpl/rpl-conf.h"
|
||||
#include "net/rpl/rpl-private.h"
|
||||
|
||||
/*
|
||||
* The body of this rule should be compiled only when "nbr_routes" is available,
|
||||
* otherwise a link error causes build failure. "nbr_routes" is compiled if
|
||||
* UIP_CONF_MAX_ROUTES != 0. See uip-ds6-route.c.
|
||||
*/
|
||||
#if UIP_CONF_MAX_ROUTES != 0
|
||||
|
||||
#if ORCHESTRA_UNICAST_SENDER_BASED && ORCHESTRA_COLLISION_FREE_HASH
|
||||
#define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < (ORCHESTRA_MAX_HASH + 1)) ? LINK_OPTION_SHARED : 0)
|
||||
|
@ -211,3 +219,5 @@ struct orchestra_rule unicast_per_neighbor_rpl_storing = {
|
|||
child_added,
|
||||
child_removed,
|
||||
};
|
||||
|
||||
#endif /* UIP_MAX_ROUTES */
|
||||
|
|
|
@ -1309,7 +1309,6 @@ cfs_coffee_configure_log(const char *filename, unsigned log_size,
|
|||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if COFFEE_IO_SEMANTICS
|
||||
int
|
||||
cfs_coffee_set_io_semantics(int fd, unsigned flags)
|
||||
{
|
||||
|
@ -1321,7 +1320,6 @@ cfs_coffee_set_io_semantics(int fd, unsigned flags)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
cfs_coffee_format(void)
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
#define UIP_CONF_ND6_SEND_RA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
|
||||
#endif /* UIP_CONF_ND6_SEND_RA */
|
||||
|
||||
/* UIP_CONF_ND6_SEND_NA enables standard IPv6 Neighbor Discovery Protocol.
|
||||
/* UIP_CONF_ND6_SEND_NS enables standard IPv6 Neighbor Discovery Protocol.
|
||||
We enable it by default when IPv6 is used without RPL.
|
||||
With RPL, the neighbor cache (link-local IPv6 <-> MAC address mapping)
|
||||
is fed whenever receiving DIO and DAO messages. This is always sufficient
|
||||
|
@ -221,9 +221,15 @@
|
|||
neighbor to us is weak, if DIO transmissions are suppressed (Trickle
|
||||
timer) or if the neighbor chooses not to transmit DIOs because it is
|
||||
a leaf node or for any reason. */
|
||||
#ifndef UIP_CONF_ND6_SEND_NS
|
||||
#define UIP_CONF_ND6_SEND_NS (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
|
||||
#endif /* UIP_CONF_ND6_SEND_NS */
|
||||
/* UIP_CONF_ND6_SEND_NA allows to still comply with NDP even if the host does
|
||||
not perform NUD or DAD processes. By default it is activated so the host
|
||||
can still communicate with a full NDP peer. */
|
||||
#ifndef UIP_CONF_ND6_SEND_NA
|
||||
#define UIP_CONF_ND6_SEND_NA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
|
||||
#endif /* UIP_CONF_ND6_SEND_NA */
|
||||
#define UIP_CONF_ND6_SEND_NA (NETSTACK_CONF_WITH_IPV6)
|
||||
#endif /* UIP_CONF_ND6_SEND_NS */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* 6lowpan configuration options.
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
#include "contiki.h"
|
||||
#include "sys/cc.h"
|
||||
#include "contiki-net.h"
|
||||
|
@ -37,10 +40,8 @@
|
|||
|
||||
#include "tcp-socket.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void relisten(struct tcp_socket *s);
|
||||
|
||||
LIST(socketlist);
|
||||
|
@ -80,7 +81,7 @@ acked(struct tcp_socket *s)
|
|||
s->output_data_maxlen - s->output_data_send_nxt);
|
||||
}
|
||||
if(s->output_data_len < s->output_data_send_nxt) {
|
||||
printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n",
|
||||
PRINTF("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n",
|
||||
s->output_data_len,
|
||||
s->output_data_send_nxt);
|
||||
tcp_markconn(uip_conn, NULL);
|
||||
|
@ -121,7 +122,7 @@ newdata(struct tcp_socket *s)
|
|||
bytesleft = 0;
|
||||
}
|
||||
if(bytesleft > 0) {
|
||||
printf("tcp: newdata, bytesleft > 0 (%d) not implemented\n", bytesleft);
|
||||
PRINTF("tcp: newdata, bytesleft > 0 (%d) not implemented\n", bytesleft);
|
||||
}
|
||||
dataptr += copylen;
|
||||
len -= copylen;
|
||||
|
@ -356,6 +357,8 @@ tcp_socket_send(struct tcp_socket *s,
|
|||
s->output_senddata_len = s->output_data_len;
|
||||
}
|
||||
|
||||
tcpip_poll_tcp(s->c);
|
||||
|
||||
return len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -398,3 +401,9 @@ tcp_socket_max_sendlen(struct tcp_socket *s)
|
|||
return s->output_data_maxlen - s->output_data_len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
tcp_socket_queuelen(struct tcp_socket *s)
|
||||
{
|
||||
return s->output_data_len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -284,4 +284,16 @@ int tcp_socket_unregister(struct tcp_socket *s);
|
|||
*/
|
||||
int tcp_socket_max_sendlen(struct tcp_socket *s);
|
||||
|
||||
/**
|
||||
* \brief The number of bytes waiting to be sent
|
||||
* \param s A pointer to a TCP socket
|
||||
* \return The number of bytes that have not yet been acknowledged by the receiver.
|
||||
*
|
||||
* This function queries the TCP socket and returns the
|
||||
* number of bytes that are currently not yet known to
|
||||
* have been successfully received by the receiver.
|
||||
*
|
||||
*/
|
||||
int tcp_socket_queuelen(struct tcp_socket *s);
|
||||
|
||||
#endif /* TCP_SOCKET_H */
|
||||
|
|
|
@ -662,7 +662,7 @@ tcpip_ipv6_output(void)
|
|||
|
||||
nbr = uip_ds6_nbr_lookup(nexthop);
|
||||
if(nbr == NULL) {
|
||||
#if UIP_ND6_SEND_NA
|
||||
#if UIP_ND6_SEND_NS
|
||||
if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE, NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
|
||||
uip_clear_buf();
|
||||
PRINTF("tcpip_ipv6_output: failed to add neighbor to cache\n");
|
||||
|
@ -691,13 +691,13 @@ tcpip_ipv6_output(void)
|
|||
nbr->nscount = 1;
|
||||
/* Send the first NS try from here (multicast destination IP address). */
|
||||
}
|
||||
#else /* UIP_ND6_SEND_NA */
|
||||
#else /* UIP_ND6_SEND_NS */
|
||||
PRINTF("tcpip_ipv6_output: neighbor not in cache\n");
|
||||
uip_len = 0;
|
||||
return;
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
} else {
|
||||
#if UIP_ND6_SEND_NA
|
||||
#if UIP_ND6_SEND_NS
|
||||
if(nbr->state == NBR_INCOMPLETE) {
|
||||
PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
|
@ -719,7 +719,7 @@ tcpip_ipv6_output(void)
|
|||
nbr->nscount = 0;
|
||||
PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
|
||||
}
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
tcpip_output(uip_ds6_nbr_get_ll(nbr));
|
||||
|
||||
|
|
|
@ -88,19 +88,23 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr,
|
|||
, reason, data);
|
||||
if(nbr) {
|
||||
uip_ipaddr_copy(&nbr->ipaddr, ipaddr);
|
||||
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
|
||||
#if UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
|
||||
nbr->isrouter = isrouter;
|
||||
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
|
||||
#endif /* UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
|
||||
nbr->state = state;
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
uip_packetqueue_new(&nbr->packethandle);
|
||||
#endif /* UIP_CONF_IPV6_QUEUE_PKT */
|
||||
#if UIP_ND6_SEND_NA
|
||||
/* timers are set separately, for now we put them in expired state */
|
||||
#if UIP_ND6_SEND_NS
|
||||
if(nbr->state == NBR_REACHABLE) {
|
||||
stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
|
||||
} else {
|
||||
/* We set the timer in expired state */
|
||||
stimer_set(&nbr->reachable, 0);
|
||||
}
|
||||
stimer_set(&nbr->sendns, 0);
|
||||
nbr->nscount = 0;
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
PRINTF("Adding neighbor with ip addr ");
|
||||
PRINT6ADDR(ipaddr);
|
||||
PRINTF(" link addr ");
|
||||
|
@ -241,7 +245,7 @@ uip_ds6_link_neighbor_callback(int status, int numtx)
|
|||
#endif /* UIP_DS6_LL_NUD */
|
||||
|
||||
}
|
||||
#if UIP_ND6_SEND_NA
|
||||
#if UIP_ND6_SEND_NS
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** Periodic processing on neighbors */
|
||||
void
|
||||
|
@ -322,6 +326,18 @@ uip_ds6_neighbor_periodic(void)
|
|||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_ds6_nbr_refresh_reachable_state(const uip_ipaddr_t *ipaddr)
|
||||
{
|
||||
uip_ds6_nbr_t *nbr;
|
||||
nbr = uip_ds6_nbr_lookup(ipaddr);
|
||||
if(nbr != NULL) {
|
||||
nbr->state = NBR_REACHABLE;
|
||||
nbr->nscount = 0;
|
||||
stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uip_ds6_nbr_t *
|
||||
uip_ds6_get_least_lifetime_neighbor(void)
|
||||
{
|
||||
|
@ -340,6 +356,6 @@ uip_ds6_get_least_lifetime_neighbor(void)
|
|||
}
|
||||
return nbr_expiring;
|
||||
}
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
|
|
@ -69,11 +69,11 @@ typedef struct uip_ds6_nbr {
|
|||
uip_ipaddr_t ipaddr;
|
||||
uint8_t isrouter;
|
||||
uint8_t state;
|
||||
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA
|
||||
#if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA
|
||||
struct stimer reachable;
|
||||
struct stimer sendns;
|
||||
uint8_t nscount;
|
||||
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA */
|
||||
#endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA */
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
struct uip_packetqueue_handle packethandle;
|
||||
#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4
|
||||
|
@ -98,6 +98,17 @@ void uip_ds6_link_neighbor_callback(int status, int numtx);
|
|||
void uip_ds6_neighbor_periodic(void);
|
||||
int uip_ds6_nbr_num(void);
|
||||
|
||||
#if UIP_ND6_SEND_NS
|
||||
/**
|
||||
* \brief Refresh the reachable state of a neighbor. This function
|
||||
* may be called when a node receives an IPv6 message that confirms the
|
||||
* reachability of a neighbor.
|
||||
* \param ipaddr pointer to the IPv6 address whose neighbor reachability state
|
||||
* should be refreshed.
|
||||
*/
|
||||
void uip_ds6_nbr_refresh_reachable_state(const uip_ipaddr_t *ipaddr);
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* This searches inside the neighbor table for the neighbor that is about to
|
||||
|
|
|
@ -573,6 +573,12 @@ uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uip_ds6_defrt_t *
|
||||
uip_ds6_defrt_head(void)
|
||||
{
|
||||
return list_head(defaultrouterlist);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uip_ds6_defrt_t *
|
||||
uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval)
|
||||
{
|
||||
uip_ds6_defrt_t *d;
|
||||
|
|
|
@ -177,6 +177,7 @@ typedef struct uip_ds6_defrt {
|
|||
|
||||
/** \name Default router list basic routines */
|
||||
/** @{ */
|
||||
uip_ds6_defrt_t *uip_ds6_defrt_head(void);
|
||||
uip_ds6_defrt_t *uip_ds6_defrt_add(uip_ipaddr_t *ipaddr,
|
||||
unsigned long interval);
|
||||
void uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt);
|
||||
|
|
|
@ -187,9 +187,9 @@ uip_ds6_periodic(void)
|
|||
}
|
||||
#endif /* !UIP_CONF_ROUTER */
|
||||
|
||||
#if UIP_ND6_SEND_NA
|
||||
#if UIP_ND6_SEND_NS
|
||||
uip_ds6_neighbor_periodic();
|
||||
#endif /* UIP_ND6_SEND_RA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
|
||||
/* Periodic RA sending */
|
||||
|
|
|
@ -116,13 +116,16 @@ void uip_log(char *msg);
|
|||
#define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
|
||||
/** @} */
|
||||
|
||||
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
|
||||
#if UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
|
||||
static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/
|
||||
static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */
|
||||
static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/
|
||||
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
|
||||
static uip_ds6_addr_t *addr; /** Pointer to an interface address */
|
||||
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
|
||||
#endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
|
||||
|
||||
#if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
|
||||
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
|
||||
#endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
|
||||
|
||||
#if !UIP_CONF_ROUTER // TBD see if we move it to ra_input
|
||||
static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */
|
||||
|
@ -157,7 +160,27 @@ create_llao(uint8_t *llao, uint8_t type) {
|
|||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Neighbor Solicitation Processing
|
||||
*
|
||||
* The NS can be received in 3 cases (procedures):
|
||||
* - sender is performing DAD (ip src = unspecified, no SLLAO option)
|
||||
* - sender is performing NUD (ip dst = unicast)
|
||||
* - sender is performing address resolution (ip dest = solicited node mcast
|
||||
* address)
|
||||
*
|
||||
* We do:
|
||||
* - if the tgt belongs to me, reply, otherwise ignore
|
||||
* - if i was performing DAD for the same address, two cases:
|
||||
* -- I already sent a NS, hence I win
|
||||
* -- I did not send a NS yet, hence I lose
|
||||
*
|
||||
* If we need to send a NA in response (i.e. the NS was done for NUD, or
|
||||
* address resolution, or DAD and there is a conflict), we do it in this
|
||||
* function: set src, dst, tgt address in the three cases, then for all cases
|
||||
* set the rest, including SLLAO
|
||||
*
|
||||
*/
|
||||
#if UIP_ND6_SEND_NA
|
||||
static void
|
||||
ns_input(void)
|
||||
|
@ -238,9 +261,9 @@ ns_input(void)
|
|||
|
||||
addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
|
||||
if(addr != NULL) {
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
|
||||
/* DAD CASE */
|
||||
#if UIP_ND6_DEF_MAXDADNS > 0
|
||||
#if UIP_CONF_IPV6_CHECKS
|
||||
if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
|
||||
PRINTF("NS received is bad\n");
|
||||
|
@ -258,9 +281,7 @@ ns_input(void)
|
|||
goto discard;
|
||||
}
|
||||
#else /* UIP_ND6_DEF_MAXDADNS > 0 */
|
||||
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
|
||||
/* DAD CASE */
|
||||
goto discard;
|
||||
goto discard; /* DAD CASE */
|
||||
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
|
||||
}
|
||||
#if UIP_CONF_IPV6_CHECKS
|
||||
|
@ -348,6 +369,7 @@ discard:
|
|||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
#if UIP_ND6_SEND_NS
|
||||
void
|
||||
uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
|
||||
{
|
||||
|
@ -410,7 +432,9 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
|
|||
PRINTF("\n");
|
||||
return;
|
||||
}
|
||||
#if UIP_ND6_SEND_NA
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
#if UIP_ND6_SEND_NS
|
||||
/*------------------------------------------------------------------*/
|
||||
/**
|
||||
* Neighbor Advertisement Processing
|
||||
|
@ -522,14 +546,11 @@ na_input(void)
|
|||
goto discard;
|
||||
}
|
||||
|
||||
if(is_solicited) {
|
||||
nbr->state = NBR_REACHABLE;
|
||||
nbr->nscount = 0;
|
||||
|
||||
/* reachable time is stored in ms */
|
||||
stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
|
||||
|
||||
} else {
|
||||
/* Note: No need to refresh the state of the nbr here.
|
||||
* It has already been refreshed upon receiving the unicast IPv6 ND packet.
|
||||
* See: uip_ds6_nbr_refresh_reachable_state()
|
||||
*/
|
||||
if(!is_solicited) {
|
||||
nbr->state = NBR_STALE;
|
||||
}
|
||||
nbr->isrouter = is_router;
|
||||
|
@ -552,11 +573,10 @@ na_input(void)
|
|||
goto discard;
|
||||
}
|
||||
}
|
||||
if(is_solicited) {
|
||||
nbr->state = NBR_REACHABLE;
|
||||
/* reachable time is stored in ms */
|
||||
stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
|
||||
}
|
||||
/* Note: No need to refresh the state of the nbr here.
|
||||
* It has already been refreshed upon receiving the unicast IPv6 ND packet.
|
||||
* See: uip_ds6_nbr_refresh_reachable_state()
|
||||
*/
|
||||
}
|
||||
}
|
||||
if(nbr->isrouter && !is_router) {
|
||||
|
@ -589,7 +609,7 @@ discard:
|
|||
uip_clear_buf();
|
||||
return;
|
||||
}
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
#if UIP_CONF_ROUTER
|
||||
#if UIP_ND6_SEND_RA
|
||||
|
@ -1083,6 +1103,8 @@ discard:
|
|||
#if UIP_ND6_SEND_NA
|
||||
UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
|
||||
ns_input);
|
||||
#endif
|
||||
#if UIP_ND6_SEND_NS
|
||||
UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
|
||||
na_input);
|
||||
#endif
|
||||
|
@ -1100,19 +1122,16 @@ UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
|
|||
void
|
||||
uip_nd6_init()
|
||||
{
|
||||
|
||||
#if UIP_ND6_SEND_NA
|
||||
/* Only handle NSs if we are prepared to send out NAs */
|
||||
uip_icmp6_register_input_handler(&ns_input_handler);
|
||||
|
||||
/*
|
||||
* Only handle NAs if we are prepared to send out NAs.
|
||||
* This is perhaps logically incorrect, but this condition was present in
|
||||
* uip_process and we keep it until proven wrong
|
||||
*/
|
||||
uip_icmp6_register_input_handler(&na_input_handler);
|
||||
#endif
|
||||
|
||||
#if UIP_ND6_SEND_NS
|
||||
/*
|
||||
* Only handle NAs if we are prepared to send out NSs. */
|
||||
uip_icmp6_register_input_handler(&na_input_handler);
|
||||
#endif
|
||||
|
||||
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
|
||||
/* Only accept RS if we are a router and happy to send out RAs */
|
||||
|
|
|
@ -60,11 +60,23 @@
|
|||
/** \name RFC 4861 Host constant */
|
||||
/** @{ */
|
||||
/** \brief Maximum router solicitation delay */
|
||||
#ifndef UIP_CONF_ND6_MAX_RTR_SOLICITATION_DELAY
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1
|
||||
#else
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY UIP_CONF_ND6_MAX_RTR_SOLICITATION_DELAY
|
||||
#endif
|
||||
/** \brief Router solicitation interval */
|
||||
#ifndef UIP_CONF_ND6_RTR_SOLICITATION_INTERVAL
|
||||
#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4
|
||||
#else
|
||||
#define UIP_ND6_RTR_SOLICITATION_INTERVAL UIP_CONF_ND6_RTR_SOLICITATION_INTERVAL
|
||||
#endif
|
||||
/** \brief Maximum router solicitations */
|
||||
#ifndef UIP_CONF_ND6_MAX_RTR_SOLICITATIONS
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3
|
||||
#else
|
||||
#define UIP_ND6_MAX_RTR_SOLICITATIONS UIP_CONF_ND6_MAX_RTR_SOLICITATIONS
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/** \name RFC 4861 Router constants */
|
||||
|
@ -74,6 +86,11 @@
|
|||
#else
|
||||
#define UIP_ND6_SEND_RA UIP_CONF_ND6_SEND_RA
|
||||
#endif
|
||||
#ifndef UIP_CONF_ND6_SEND_NS
|
||||
#define UIP_ND6_SEND_NS 1 /* enable/disable NS sending */
|
||||
#else
|
||||
#define UIP_ND6_SEND_NS UIP_CONF_ND6_SEND_NS
|
||||
#endif
|
||||
#ifndef UIP_CONF_ND6_SEND_NA
|
||||
#define UIP_ND6_SEND_NA 1 /* enable/disable NA sending */
|
||||
#else
|
||||
|
@ -91,7 +108,11 @@
|
|||
#endif
|
||||
#define UIP_ND6_M_FLAG 0
|
||||
#define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL)
|
||||
#ifndef UIP_CONF_ROUTER_LIFETIME
|
||||
#define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL
|
||||
#else
|
||||
#define UIP_ND6_ROUTER_LIFETIME UIP_CONF_ROUTER_LIFETIME
|
||||
#endif
|
||||
|
||||
#define UIP_ND6_MAX_INITIAL_RA_INTERVAL 16 /*seconds*/
|
||||
#define UIP_ND6_MAX_INITIAL_RAS 3 /*transmissions*/
|
||||
|
@ -109,7 +130,7 @@
|
|||
#if UIP_CONF_LL_802154
|
||||
#define UIP_ND6_DEF_MAXDADNS 0
|
||||
#else /* UIP_CONF_LL_802154 */
|
||||
#define UIP_ND6_DEF_MAXDADNS UIP_ND6_SEND_NA
|
||||
#define UIP_ND6_DEF_MAXDADNS UIP_ND6_SEND_NS
|
||||
#endif /* UIP_CONF_LL_802154 */
|
||||
#else /* UIP_CONF_ND6_DEF_MAXDADNS */
|
||||
#define UIP_ND6_DEF_MAXDADNS UIP_CONF_ND6_DEF_MAXDADNS
|
||||
|
@ -335,30 +356,6 @@ typedef struct uip_nd6_opt_redirected_hdr {
|
|||
* \name ND Messages Processing and Generation
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \brief Process a neighbor solicitation
|
||||
*
|
||||
* The NS can be received in 3 cases (procedures):
|
||||
* - sender is performing DAD (ip src = unspecified, no SLLAO option)
|
||||
* - sender is performing NUD (ip dst = unicast)
|
||||
* - sender is performing address resolution (ip dest = solicited node mcast
|
||||
* address)
|
||||
*
|
||||
* We do:
|
||||
* - if the tgt belongs to me, reply, otherwise ignore
|
||||
* - if i was performing DAD for the same address, two cases:
|
||||
* -- I already sent a NS, hence I win
|
||||
* -- I did not send a NS yet, hence I lose
|
||||
*
|
||||
* If we need to send a NA in response (i.e. the NS was done for NUD, or
|
||||
* address resolution, or DAD and there is a conflict), we do it in this
|
||||
* function: set src, dst, tgt address in the three cases, then for all cases
|
||||
* set the rest, including SLLAO
|
||||
*
|
||||
*/
|
||||
void
|
||||
uip_nd6_ns_input(void);
|
||||
|
||||
/**
|
||||
* \brief Send a neighbor solicitation, send a Neighbor Advertisement
|
||||
* \param src pointer to the src of the NS if known
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
#include "rpl/rpl-private.h"
|
||||
#endif
|
||||
|
||||
#if UIP_ND6_SEND_NS
|
||||
#include "net/ipv6/uip-ds6-nbr.h"
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -1151,6 +1155,13 @@ uip_process(uint8_t flag)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
/* Refresh neighbor state after receiving a unicast message */
|
||||
#if UIP_ND6_SEND_NS
|
||||
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||
uip_ds6_nbr_refresh_reachable_state(&UIP_IP_BUF->srcipaddr);
|
||||
}
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
#if UIP_CONF_ROUTER
|
||||
/*
|
||||
* Next header field processing. In IPv6, we can have extension headers,
|
||||
|
|
347
core/net/ipv6/websocket-http-client.c
Normal file
347
core/net/ipv6/websocket-http-client.c
Normal file
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Thingsquare, http://www.thingsquare.com/.
|
||||
* 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.
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "websocket-http-client.h"
|
||||
#include "net/ip/uiplib.h"
|
||||
#include "net/ip/resolv.h"
|
||||
|
||||
#include "ip64-addr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
enum {
|
||||
STATE_WAITING_FOR_HEADER,
|
||||
STATE_WAITING_FOR_CONNECTED,
|
||||
STATE_STEADY_STATE,
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
send_get(struct websocket_http_client_state *s)
|
||||
{
|
||||
struct tcp_socket *tcps;
|
||||
|
||||
tcps = &s->s;
|
||||
tcp_socket_send_str(tcps, "GET ");
|
||||
tcp_socket_send_str(tcps, s->file);
|
||||
tcp_socket_send_str(tcps, " HTTP/1.1\r\n");
|
||||
tcp_socket_send_str(tcps, "Host: ");
|
||||
tcp_socket_send_str(tcps, s->host);
|
||||
tcp_socket_send_str(tcps, "\r\n");
|
||||
if(strlen(s->header) > 0) {
|
||||
tcp_socket_send_str(tcps, s->header);
|
||||
}
|
||||
/* The Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== header is
|
||||
supposed to be a random value, encoded as base64, that is SHA1
|
||||
hashed by the server and returned in a HTTP header. This is used
|
||||
to make sure that we are not seeing some cached version of this
|
||||
conversation. But we have no SHA1 code by default in Contiki, so
|
||||
we can't check the return value. Therefore we just use a
|
||||
hardcoded value here. */
|
||||
tcp_socket_send_str(tcps,
|
||||
"Connection: Upgrade\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
"Sec-WebSocket-Protocol:");
|
||||
tcp_socket_send_str(tcps, s->subprotocol);
|
||||
tcp_socket_send_str(tcps, "\r\n");
|
||||
tcp_socket_send_str(tcps, "\r\n");
|
||||
PRINTF("websocket-http-client: send_get(): output buffer left %d\n", tcp_socket_max_sendlen(tcps));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
send_connect(struct websocket_http_client_state *s)
|
||||
{
|
||||
struct tcp_socket *tcps;
|
||||
char buf[20];
|
||||
|
||||
tcps = &s->s;
|
||||
tcp_socket_send_str(tcps, "CONNECT ");
|
||||
tcp_socket_send_str(tcps, s->host);
|
||||
tcp_socket_send_str(tcps, ":");
|
||||
sprintf(buf, "%d", s->port);
|
||||
tcp_socket_send_str(tcps, buf);
|
||||
tcp_socket_send_str(tcps, " HTTP/1.1\r\n");
|
||||
tcp_socket_send_str(tcps, "Host: ");
|
||||
tcp_socket_send_str(tcps, s->host);
|
||||
tcp_socket_send_str(tcps, "\r\n");
|
||||
tcp_socket_send_str(tcps, "Proxy-Connection: Keep-Alive\r\n\r\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
event(struct tcp_socket *tcps, void *ptr,
|
||||
tcp_socket_event_t e)
|
||||
{
|
||||
struct websocket_http_client_state *s = ptr;
|
||||
|
||||
if(e == TCP_SOCKET_CONNECTED) {
|
||||
if(s->proxy_port != 0) {
|
||||
send_connect(s);
|
||||
} else {
|
||||
send_get(s);
|
||||
}
|
||||
} else if(e == TCP_SOCKET_CLOSED) {
|
||||
websocket_http_client_closed(s);
|
||||
} else if(e == TCP_SOCKET_TIMEDOUT) {
|
||||
websocket_http_client_timedout(s);
|
||||
} else if(e == TCP_SOCKET_ABORTED) {
|
||||
websocket_http_client_aborted(s);
|
||||
} else if(e == TCP_SOCKET_DATA_SENT) {
|
||||
/* We could feed this information up to the websocket.c layer, but
|
||||
we currently do not do that. */
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
parse_header_byte(struct websocket_http_client_state *s,
|
||||
uint8_t b)
|
||||
{
|
||||
static const char *endmarker = "\r\n\r\n";
|
||||
|
||||
PT_BEGIN(&s->parse_header_pt);
|
||||
|
||||
/* Skip the first part of the HTTP response */
|
||||
while(b != ' ') {
|
||||
PT_YIELD(&s->parse_header_pt);
|
||||
}
|
||||
|
||||
/* Skip the space that follow the first part */
|
||||
PT_YIELD(&s->parse_header_pt);
|
||||
|
||||
/* Read the first three bytes that constistute the HTTP status
|
||||
code. We store the HTTP status code as an integer in the
|
||||
s->http_status field. */
|
||||
s->http_status = (b - '0');
|
||||
PT_YIELD(&s->parse_header_pt);
|
||||
s->http_status = s->http_status * 10 + (b - '0');
|
||||
PT_YIELD(&s->parse_header_pt);
|
||||
s->http_status = s->http_status * 10 + (b - '0');
|
||||
|
||||
if((s->proxy_port != 0 && !(s->http_status == 200 || s->http_status == 101)) ||
|
||||
(s->proxy_port == 0 && s->http_status != 101)) {
|
||||
/* This is a websocket request, so the server should have answered
|
||||
with a 101 Switching protocols response. */
|
||||
PRINTF("Websocket HTTP client didn't get the 101 status code (got %d), closing connection\n",
|
||||
s->http_status);
|
||||
websocket_http_client_close(s);
|
||||
while(1) {
|
||||
PT_YIELD(&s->parse_header_pt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep eating header bytes until we reach the end of it. The end is
|
||||
indicated by the string "\r\n\r\n". We don't actually look at any
|
||||
of the headers.
|
||||
|
||||
The s->i variable contains the number of consecutive bytes
|
||||
matched. If we match the total length of the string, we stop.
|
||||
*/
|
||||
|
||||
s->i = 0;
|
||||
do {
|
||||
PT_YIELD(&s->parse_header_pt);
|
||||
if(b == (uint8_t)endmarker[s->i]) {
|
||||
s->i++;
|
||||
} else {
|
||||
s->i = 0;
|
||||
}
|
||||
} while(s->i < strlen(endmarker));
|
||||
|
||||
if(s->proxy_port != 0 && s->state == STATE_WAITING_FOR_HEADER) {
|
||||
send_get(s);
|
||||
s->state = STATE_WAITING_FOR_CONNECTED;
|
||||
} else {
|
||||
s->state = STATE_STEADY_STATE;
|
||||
websocket_http_client_connected(s);
|
||||
}
|
||||
PT_END(&s->parse_header_pt);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
input(struct tcp_socket *tcps, void *ptr,
|
||||
const uint8_t *inputptr, int inputdatalen)
|
||||
{
|
||||
struct websocket_http_client_state *s = ptr;
|
||||
|
||||
if(s->state == STATE_WAITING_FOR_HEADER ||
|
||||
s->state == STATE_WAITING_FOR_CONNECTED) {
|
||||
int i;
|
||||
for(i = 0; i < inputdatalen; i++) {
|
||||
parse_header_byte(s, inputptr[i]);
|
||||
if(s->state == STATE_STEADY_STATE) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i < inputdatalen && s->state == STATE_STEADY_STATE) {
|
||||
websocket_http_client_datahandler(s, &inputptr[i], inputdatalen - i);
|
||||
}
|
||||
} else {
|
||||
websocket_http_client_datahandler(s, inputptr, inputdatalen);
|
||||
}
|
||||
|
||||
return 0; /* all data consumed */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_http_client_register(struct websocket_http_client_state *s,
|
||||
const char *host,
|
||||
uint16_t port,
|
||||
const char *file,
|
||||
const char *subprotocol,
|
||||
const char *header)
|
||||
{
|
||||
if(host == NULL) {
|
||||
return -1;
|
||||
}
|
||||
strncpy(s->host, host, sizeof(s->host));
|
||||
|
||||
if(file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
strncpy(s->file, file, sizeof(s->file));
|
||||
|
||||
if(subprotocol == NULL) {
|
||||
return -1;
|
||||
}
|
||||
strncpy(s->subprotocol, subprotocol, sizeof(s->subprotocol));
|
||||
|
||||
if(header == NULL) {
|
||||
strncpy(s->header, "", sizeof(s->header));
|
||||
} else {
|
||||
strncpy(s->header, header, sizeof(s->header));
|
||||
}
|
||||
|
||||
if(port == 0) {
|
||||
s->port = 80;
|
||||
} else {
|
||||
s->port = port;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_http_client_get(struct websocket_http_client_state *s)
|
||||
{
|
||||
uip_ip4addr_t ip4addr;
|
||||
uip_ip6addr_t ip6addr;
|
||||
uip_ip6addr_t *addr;
|
||||
uint16_t port;
|
||||
|
||||
PRINTF("websocket_http_client_get: connecting to %s with file %s subprotocol %s header %s\n",
|
||||
s->host, s->file, s->subprotocol, s->header);
|
||||
|
||||
|
||||
s->state = STATE_WAITING_FOR_HEADER;
|
||||
|
||||
if(tcp_socket_register(&s->s, s,
|
||||
s->inputbuf, sizeof(s->inputbuf),
|
||||
s->outputbuf, sizeof(s->outputbuf),
|
||||
input, event) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
port = s->port;
|
||||
if(s->proxy_port != 0) {
|
||||
/* The proxy address should be an IPv6 address. */
|
||||
uip_ipaddr_copy(&ip6addr, &s->proxy_addr);
|
||||
port = s->proxy_port;
|
||||
} else if(uiplib_ip6addrconv(s->host, &ip6addr) == 0) {
|
||||
/* First check if the host is an IP address. */
|
||||
if(uiplib_ip4addrconv(s->host, &ip4addr) != 0) {
|
||||
ip64_addr_4to6(&ip4addr, &ip6addr);
|
||||
} else {
|
||||
/* Try to lookup the hostname. If it fails, we initiate a hostname
|
||||
lookup. */
|
||||
if(resolv_lookup(s->host, &addr) != RESOLV_STATUS_CACHED) {
|
||||
return -1;
|
||||
}
|
||||
return tcp_socket_connect(&s->s, addr, s->port);
|
||||
}
|
||||
}
|
||||
return tcp_socket_connect(&s->s, &ip6addr, port);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_http_client_send(struct websocket_http_client_state *s,
|
||||
const uint8_t *data,
|
||||
uint16_t datalen)
|
||||
{
|
||||
if(s->state == STATE_STEADY_STATE) {
|
||||
return tcp_socket_send(&s->s, data, datalen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_http_client_sendbuflen(struct websocket_http_client_state *s)
|
||||
{
|
||||
return tcp_socket_max_sendlen(&s->s);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
websocket_http_client_close(struct websocket_http_client_state *s)
|
||||
{
|
||||
tcp_socket_close(&s->s);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
const char *
|
||||
websocket_http_client_hostname(struct websocket_http_client_state *s)
|
||||
{
|
||||
return s->host;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
websocket_http_client_init(struct websocket_http_client_state *s)
|
||||
{
|
||||
uip_create_unspecified(&s->proxy_addr);
|
||||
s->proxy_port = 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
websocket_http_client_set_proxy(struct websocket_http_client_state *s,
|
||||
const uip_ipaddr_t *addr, uint16_t port)
|
||||
{
|
||||
uip_ipaddr_copy(&s->proxy_addr, addr);
|
||||
s->proxy_port = port;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_http_client_queuelen(struct websocket_http_client_state *s)
|
||||
{
|
||||
return tcp_socket_queuelen(&s->s);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
123
core/net/ipv6/websocket-http-client.h
Normal file
123
core/net/ipv6/websocket-http-client.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Thingsquare, http://www.thingsquare.com/.
|
||||
* 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.
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef WEBSOCKET_HTTP_CLIENT_H_
|
||||
#define WEBSOCKET_HTTP_CLIENT_H_
|
||||
|
||||
#include "contiki.h"
|
||||
#include "tcp-socket.h"
|
||||
|
||||
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE
|
||||
#define WEBSOCKET_HTTP_CLIENT_INPUTBUFSIZE WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE
|
||||
#else /* WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE */
|
||||
#define WEBSOCKET_HTTP_CLIENT_INPUTBUFSIZE 100
|
||||
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE */
|
||||
|
||||
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE
|
||||
#define WEBSOCKET_HTTP_CLIENT_OUTPUTBUFSIZE WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE
|
||||
#else /* WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE */
|
||||
#define WEBSOCKET_HTTP_CLIENT_OUTPUTBUFSIZE 300
|
||||
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE */
|
||||
|
||||
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_HOSTLEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN
|
||||
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN */
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_HOSTLEN 32
|
||||
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN */
|
||||
|
||||
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_FILELEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN
|
||||
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN */
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_FILELEN 32
|
||||
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN */
|
||||
|
||||
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_SUBPROTOCOLLEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN
|
||||
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN */
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_SUBPROTOCOLLEN 24
|
||||
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN */
|
||||
|
||||
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_HEADERLEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN
|
||||
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN */
|
||||
#define WEBSOCKET_HTTP_CLIENT_MAX_HEADERLEN 128
|
||||
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN */
|
||||
|
||||
struct websocket_http_client_state {
|
||||
struct tcp_socket s;
|
||||
uint8_t inputbuf[WEBSOCKET_HTTP_CLIENT_INPUTBUFSIZE];
|
||||
uint8_t outputbuf[WEBSOCKET_HTTP_CLIENT_OUTPUTBUFSIZE];
|
||||
char host[WEBSOCKET_HTTP_CLIENT_MAX_HOSTLEN];
|
||||
char file[WEBSOCKET_HTTP_CLIENT_MAX_FILELEN];
|
||||
char subprotocol[WEBSOCKET_HTTP_CLIENT_MAX_SUBPROTOCOLLEN];
|
||||
char header[WEBSOCKET_HTTP_CLIENT_MAX_HEADERLEN];
|
||||
uint16_t port;
|
||||
|
||||
int state;
|
||||
struct pt parse_header_pt;
|
||||
int http_status;
|
||||
int i;
|
||||
|
||||
uip_ipaddr_t proxy_addr;
|
||||
uint16_t proxy_port;
|
||||
};
|
||||
|
||||
void websocket_http_client_init(struct websocket_http_client_state *s);
|
||||
void websocket_http_client_set_proxy(struct websocket_http_client_state *s,
|
||||
const uip_ipaddr_t *addr, uint16_t port);
|
||||
|
||||
int websocket_http_client_register(struct websocket_http_client_state *s,
|
||||
const char *host,
|
||||
uint16_t port,
|
||||
const char *file,
|
||||
const char *subprotocol,
|
||||
const char *hdr);
|
||||
int websocket_http_client_get(struct websocket_http_client_state *s);
|
||||
int websocket_http_client_send(struct websocket_http_client_state *s,
|
||||
const uint8_t *data,
|
||||
uint16_t datalen);
|
||||
int websocket_http_client_sendbuflen(struct websocket_http_client_state *s);
|
||||
|
||||
void websocket_http_client_close(struct websocket_http_client_state *s);
|
||||
|
||||
const char *websocket_http_client_hostname(struct websocket_http_client_state *s);
|
||||
|
||||
int websocket_http_client_queuelen(struct websocket_http_client_state *s);
|
||||
|
||||
/* Callback functions that have to be implemented by the application
|
||||
program. */
|
||||
void websocket_http_client_datahandler(struct websocket_http_client_state *s,
|
||||
const uint8_t *data, uint16_t len);
|
||||
void websocket_http_client_connected(struct websocket_http_client_state *s);
|
||||
void websocket_http_client_timedout(struct websocket_http_client_state *s);
|
||||
void websocket_http_client_aborted(struct websocket_http_client_state *s);
|
||||
void websocket_http_client_closed(struct websocket_http_client_state *s);
|
||||
|
||||
#endif /* WEBSOCKET_HTTP_CLIENT_H_ */
|
724
core/net/ipv6/websocket.c
Normal file
724
core/net/ipv6/websocket.c
Normal file
|
@ -0,0 +1,724 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
|
||||
* 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.
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "contiki-net.h"
|
||||
#include "lib/petsciiconv.h"
|
||||
|
||||
#include "websocket.h"
|
||||
|
||||
PROCESS(websocket_process, "Websockets process");
|
||||
|
||||
#define MAX_HOSTLEN 64
|
||||
#define MAX_PATHLEN 100
|
||||
|
||||
LIST(websocketlist);
|
||||
|
||||
#define WEBSOCKET_FIN_BIT 0x80
|
||||
|
||||
#define WEBSOCKET_OPCODE_MASK 0x0f
|
||||
#define WEBSOCKET_OPCODE_CONT 0x00
|
||||
#define WEBSOCKET_OPCODE_TEXT 0x01
|
||||
#define WEBSOCKET_OPCODE_BIN 0x02
|
||||
#define WEBSOCKET_OPCODE_CLOSE 0x08
|
||||
#define WEBSOCKET_OPCODE_PING 0x09
|
||||
#define WEBSOCKET_OPCODE_PONG 0x0a
|
||||
|
||||
#define WEBSOCKET_MASK_BIT 0x80
|
||||
#define WEBSOCKET_LEN_MASK 0x7f
|
||||
struct websocket_frame_hdr {
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t extlen[4];
|
||||
};
|
||||
|
||||
struct websocket_frame_mask {
|
||||
uint8_t mask[4];
|
||||
};
|
||||
|
||||
#define DEBUG DEBUG_NONE
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
parse_url(const char *url, char *host, uint16_t *portptr, char *path)
|
||||
{
|
||||
const char *urlptr;
|
||||
int i;
|
||||
const char *file;
|
||||
uint16_t port;
|
||||
|
||||
if(url == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't even try to go further if the URL is empty. */
|
||||
if(strlen(url) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See if the URL starts with http:// or ws:// and remove it. */
|
||||
if(strncmp(url, "http://", strlen("http://")) == 0) {
|
||||
urlptr = url + strlen("http://");
|
||||
} else if(strncmp(url, "ws://", strlen("ws://")) == 0) {
|
||||
urlptr = url + strlen("ws://");
|
||||
} else {
|
||||
urlptr = url;
|
||||
}
|
||||
|
||||
/* Find host part of the URL. */
|
||||
for(i = 0; i < MAX_HOSTLEN; ++i) {
|
||||
if(*urlptr == 0 ||
|
||||
*urlptr == '/' ||
|
||||
*urlptr == ' ' ||
|
||||
*urlptr == ':') {
|
||||
if(host != NULL) {
|
||||
host[i] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(host != NULL) {
|
||||
host[i] = *urlptr;
|
||||
}
|
||||
++urlptr;
|
||||
}
|
||||
|
||||
/* Find the port. Default is 0, which lets the underlying transport
|
||||
select its default port. */
|
||||
port = 0;
|
||||
if(*urlptr == ':') {
|
||||
port = 0;
|
||||
do {
|
||||
++urlptr;
|
||||
if(*urlptr >= '0' && *urlptr <= '9') {
|
||||
port = (10 * port) + (*urlptr - '0');
|
||||
}
|
||||
} while(*urlptr >= '0' &&
|
||||
*urlptr <= '9');
|
||||
}
|
||||
if(portptr != NULL) {
|
||||
*portptr = port;
|
||||
}
|
||||
/* Find file part of the URL. */
|
||||
while(*urlptr != '/' && *urlptr != 0) {
|
||||
++urlptr;
|
||||
}
|
||||
if(*urlptr == '/') {
|
||||
file = urlptr;
|
||||
} else {
|
||||
file = "/";
|
||||
}
|
||||
if(path != NULL) {
|
||||
strncpy(path, file, MAX_PATHLEN);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
start_get(struct websocket *s)
|
||||
{
|
||||
if(websocket_http_client_get(&(s->s)) == 0) {
|
||||
PRINTF("Out of memory error\n");
|
||||
s->state = WEBSOCKET_STATE_CLOSED;
|
||||
return WEBSOCKET_ERR;
|
||||
} else {
|
||||
PRINTF("Connecting...\n");
|
||||
s->state = WEBSOCKET_STATE_HTTP_REQUEST_SENT;
|
||||
return WEBSOCKET_OK;
|
||||
}
|
||||
return WEBSOCKET_ERR;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
call(struct websocket *s, websocket_result_t r,
|
||||
const uint8_t *data, uint16_t datalen)
|
||||
{
|
||||
if(s != NULL && s->callback != NULL) {
|
||||
s->callback(s, r, data, datalen);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(websocket_process, ev, data)
|
||||
{
|
||||
PROCESS_BEGIN();
|
||||
|
||||
while(1) {
|
||||
|
||||
PROCESS_WAIT_EVENT();
|
||||
|
||||
if(ev == resolv_event_found && data != NULL) {
|
||||
int ret;
|
||||
struct websocket *s;
|
||||
const char *name = data;
|
||||
/* Either found a hostname, or not. We need to go through the
|
||||
list of websocketsand figure out to which connection this
|
||||
reply corresponds, then either restart the HTTP get, or kill
|
||||
it (if no hostname was found). */
|
||||
for(s = list_head(websocketlist);
|
||||
s != NULL;
|
||||
s = list_item_next(s)) {
|
||||
if(strcmp(name, websocket_http_client_hostname(&s->s)) == 0) {
|
||||
ret = resolv_lookup(name, NULL);
|
||||
if(ret == RESOLV_STATUS_CACHED) {
|
||||
/* Hostname found, restart get. */
|
||||
if(s->state == WEBSOCKET_STATE_DNS_REQUEST_SENT) {
|
||||
PRINTF("Restarting get\n");
|
||||
start_get(s);
|
||||
}
|
||||
} else {
|
||||
if(s->state == WEBSOCKET_STATE_DNS_REQUEST_SENT) {
|
||||
/* Hostname not found, kill connection. */
|
||||
/* PRINTF("XXX killing connection\n");*/
|
||||
call(s, WEBSOCKET_HOSTNAME_NOT_FOUND, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Callback function. Called from the webclient when the HTTP
|
||||
* connection was abruptly aborted.
|
||||
*/
|
||||
void
|
||||
websocket_http_client_aborted(struct websocket_http_client_state *client_state)
|
||||
{
|
||||
if(client_state != NULL) {
|
||||
struct websocket *s = (struct websocket *)
|
||||
((char *)client_state - offsetof(struct websocket, s));
|
||||
PRINTF("Websocket reset\n");
|
||||
s->state = WEBSOCKET_STATE_CLOSED;
|
||||
call(s, WEBSOCKET_RESET, NULL, 0);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Callback function. Called from the webclient when the HTTP
|
||||
* connection timed out.
|
||||
*/
|
||||
void
|
||||
websocket_http_client_timedout(struct websocket_http_client_state *client_state)
|
||||
{
|
||||
if(client_state != NULL) {
|
||||
struct websocket *s = (struct websocket *)
|
||||
((char *)client_state - offsetof(struct websocket, s));
|
||||
PRINTF("Websocket timed out\n");
|
||||
s->state = WEBSOCKET_STATE_CLOSED;
|
||||
call(s, WEBSOCKET_TIMEDOUT, NULL, 0);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Callback function. Called from the webclient when the HTTP
|
||||
* connection was closed after a request from the "websocket_http_client_close()"
|
||||
* function. .
|
||||
*/
|
||||
void
|
||||
websocket_http_client_closed(struct websocket_http_client_state *client_state)
|
||||
{
|
||||
if(client_state != NULL) {
|
||||
struct websocket *s = (struct websocket *)
|
||||
((char *)client_state - offsetof(struct websocket, s));
|
||||
PRINTF("Websocket closed.\n");
|
||||
s->state = WEBSOCKET_STATE_CLOSED;
|
||||
call(s, WEBSOCKET_CLOSED, NULL, 0);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Callback function. Called from the webclient when the HTTP
|
||||
* connection is connected.
|
||||
*/
|
||||
void
|
||||
websocket_http_client_connected(struct websocket_http_client_state *client_state)
|
||||
{
|
||||
struct websocket *s = (struct websocket *)
|
||||
((char *)client_state - offsetof(struct websocket, s));
|
||||
|
||||
PRINTF("Websocket connected\n");
|
||||
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
|
||||
call(s, WEBSOCKET_CONNECTED, NULL, 0);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* The websocket header may potentially be split into multiple TCP
|
||||
segments. This function eats one byte each, puts it into
|
||||
s->headercache, and checks whether or not the full header has been
|
||||
received. */
|
||||
static int
|
||||
receive_header_byte(struct websocket *s, uint8_t byte)
|
||||
{
|
||||
int len;
|
||||
int expected_len;
|
||||
struct websocket_frame_hdr *hdr;
|
||||
|
||||
/* Take the next byte of data and place it in the header cache. */
|
||||
if(s->state == WEBSOCKET_STATE_RECEIVING_HEADER) {
|
||||
s->headercache[s->headercacheptr] = byte;
|
||||
s->headercacheptr++;
|
||||
if(s->headercacheptr >= sizeof(s->headercache)) {
|
||||
/* Something bad happened: we ad read 10 bytes and had not yet
|
||||
found a reasonable header, so we close the socket. */
|
||||
websocket_close(s);
|
||||
}
|
||||
}
|
||||
|
||||
len = s->headercacheptr;
|
||||
hdr = (struct websocket_frame_hdr *)s->headercache;
|
||||
|
||||
/* Check the header that we have received to see if it is long
|
||||
enough. */
|
||||
|
||||
/* We start with expecting a length of at least two bytes (opcode +
|
||||
1 length byte). */
|
||||
expected_len = 2;
|
||||
|
||||
if(len >= expected_len) {
|
||||
|
||||
/* We check how many more bytes we should expect to see. The
|
||||
length byte determines how many length bytes are included in
|
||||
the header. */
|
||||
if((hdr->len & WEBSOCKET_LEN_MASK) == 126) {
|
||||
expected_len += 2;
|
||||
} else if((hdr->len & WEBSOCKET_LEN_MASK) == 127) {
|
||||
expected_len += 4;
|
||||
}
|
||||
|
||||
/* If the option has the mask bit set, we should expect to see 4
|
||||
mask bytes at the end of the header. */
|
||||
if((hdr->len & WEBSOCKET_MASK_BIT ) != 0) {
|
||||
expected_len += 4;
|
||||
}
|
||||
|
||||
/* Now we know how long our header if expected to be. If it is
|
||||
this long, we are done and we set the state to reflect this. */
|
||||
if(len == expected_len) {
|
||||
s->state = WEBSOCKET_STATE_HEADER_RECEIVED;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Callback function. Called from the webclient module when HTTP data
|
||||
* has arrived.
|
||||
*/
|
||||
void
|
||||
websocket_http_client_datahandler(struct websocket_http_client_state *client_state,
|
||||
const uint8_t *data, uint16_t datalen)
|
||||
{
|
||||
struct websocket *s = (struct websocket *)
|
||||
((char *)client_state - offsetof(struct websocket, s));
|
||||
struct websocket_frame_hdr *hdr;
|
||||
struct websocket_frame_mask *maskptr;
|
||||
|
||||
if(data == NULL) {
|
||||
call(s, WEBSOCKET_CLOSED, NULL, 0);
|
||||
} else {
|
||||
/* This function is a state machine that does different things
|
||||
depending on the state. If we are waiting for header (the
|
||||
default state), we change to the RECEIVING_HEADER state when we
|
||||
get the first byte. If we are receiving header, we put all
|
||||
bytes we have into a header buffer until the full header has
|
||||
been received. If we have received the header, we parse it. If
|
||||
we have received and parsed the header, we are ready to receive
|
||||
data. Finally, if there is data left in the incoming packet, we
|
||||
repeat the process. */
|
||||
|
||||
if(s->state == WEBSOCKET_STATE_WAITING_FOR_HEADER) {
|
||||
s->state = WEBSOCKET_STATE_RECEIVING_HEADER;
|
||||
s->headercacheptr = 0;
|
||||
}
|
||||
|
||||
if(s->state == WEBSOCKET_STATE_RECEIVING_HEADER) {
|
||||
while(datalen > 0 && s->state == WEBSOCKET_STATE_RECEIVING_HEADER) {
|
||||
receive_header_byte(s, data[0]);
|
||||
data++;
|
||||
datalen--;
|
||||
}
|
||||
}
|
||||
|
||||
if(s->state == WEBSOCKET_STATE_HEADER_RECEIVED) {
|
||||
/* If this is the start of an incoming websocket data frame, we
|
||||
decode the header and check if we should act on in. If not, we
|
||||
pipe the data to the application through a callback handler. If
|
||||
data arrives in multiple packets, it is up to the application to
|
||||
put it back together again. */
|
||||
|
||||
/* The websocket header is at the start of the incoming data. */
|
||||
hdr = (struct websocket_frame_hdr *)s->headercache;
|
||||
|
||||
/* The s->left field holds the length of the application data
|
||||
* chunk that we are about to receive. */
|
||||
s->len = s->left = 0;
|
||||
|
||||
/* The s->mask field holds the bitmask of the data chunk, if
|
||||
* any. */
|
||||
memset(s->mask, 0, sizeof(s->mask));
|
||||
|
||||
/* We first read out the length of the application data
|
||||
chunk. The length may be encoded over multiple bytes. If the
|
||||
length is >= 126 bytes, it is encoded as two or more
|
||||
bytes. The first length field determines if it is in 2 or 4
|
||||
bytes. We also keep track of where the bitmask is held - its
|
||||
place also differs depending on how the length is encoded. */
|
||||
maskptr = (struct websocket_frame_mask *)hdr->extlen;
|
||||
if((hdr->len & WEBSOCKET_LEN_MASK) < 126) {
|
||||
s->len = s->left = hdr->len & WEBSOCKET_LEN_MASK;
|
||||
} else if(hdr->len == 126) {
|
||||
s->len = s->left = (hdr->extlen[0] << 8) + hdr->extlen[1];
|
||||
maskptr = (struct websocket_frame_mask *)&hdr->extlen[2];
|
||||
} else if(hdr->len == 127) {
|
||||
s->len = s->left = ((uint32_t)hdr->extlen[0] << 24) +
|
||||
((uint32_t)hdr->extlen[1] << 16) +
|
||||
((uint32_t)hdr->extlen[2] << 8) +
|
||||
hdr->extlen[3];
|
||||
maskptr = (struct websocket_frame_mask *)&hdr->extlen[4];
|
||||
}
|
||||
|
||||
/* Set user_data to point to the first byte of application data.
|
||||
See if the application data chunk is masked or not. If it is,
|
||||
we copy the bitmask into the s->mask field. */
|
||||
if((hdr->len & WEBSOCKET_MASK_BIT) == 0) {
|
||||
/* PRINTF("No mask\n");*/
|
||||
} else {
|
||||
memcpy(s->mask, &maskptr->mask, sizeof(s->mask));
|
||||
/* PRINTF("There was a mask, %02x %02x %02x %02x\n",
|
||||
s->mask[0], s->mask[1], s->mask[2], s->mask[3]);*/
|
||||
}
|
||||
|
||||
/* Remember the opcode of the application chunk, put it in the
|
||||
* s->opcode field. */
|
||||
s->opcode = hdr->opcode & WEBSOCKET_OPCODE_MASK;
|
||||
|
||||
if(s->opcode == WEBSOCKET_OPCODE_PING) {
|
||||
/* If the opcode is ping, we change the opcode to a pong, and
|
||||
* send the data back. */
|
||||
hdr->opcode = (hdr->opcode & (~WEBSOCKET_OPCODE_MASK)) |
|
||||
WEBSOCKET_OPCODE_PONG;
|
||||
websocket_http_client_send(&s->s, (const uint8_t*)hdr, 2);
|
||||
if(s->left > 0) {
|
||||
websocket_http_client_send(&s->s, (const uint8_t*)data, s->left);
|
||||
}
|
||||
PRINTF("Got ping\n");
|
||||
call(s, WEBSOCKET_PINGED, NULL, 0);
|
||||
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
|
||||
} else if(s->opcode == WEBSOCKET_OPCODE_PONG) {
|
||||
/* If the opcode is pong, we call the application to let it
|
||||
know we got a pong. */
|
||||
PRINTF("Got pong\n");
|
||||
call(s, WEBSOCKET_PONG_RECEIVED, NULL, 0);
|
||||
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
|
||||
} else if(s->opcode == WEBSOCKET_OPCODE_CLOSE) {
|
||||
/* If the opcode is a close, we send a close frame back. */
|
||||
hdr->opcode = (hdr->opcode & (~WEBSOCKET_OPCODE_MASK)) |
|
||||
WEBSOCKET_OPCODE_CLOSE;
|
||||
websocket_http_client_send(&s->s, (const uint8_t*)hdr, 2);
|
||||
if(s->left > 0) {
|
||||
websocket_http_client_send(&s->s, (const uint8_t*)data, s->left);
|
||||
}
|
||||
PRINTF("websocket: got close, sending close\n");
|
||||
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
|
||||
websocket_http_client_close(&s->s);
|
||||
} else if(s->opcode == WEBSOCKET_OPCODE_BIN ||
|
||||
s->opcode == WEBSOCKET_OPCODE_TEXT) {
|
||||
|
||||
/* If the opcode is bin or text, and there is application
|
||||
* layer data in the packet, we call the application to
|
||||
* process it. */
|
||||
if(s->left > 0) {
|
||||
s->state = WEBSOCKET_STATE_RECEIVING_DATA;
|
||||
if(datalen > 0) {
|
||||
int len;
|
||||
|
||||
len = MIN(s->left, datalen);
|
||||
/* XXX todo: mask if needed. */
|
||||
call(s, WEBSOCKET_DATA, data, len);
|
||||
data += len;
|
||||
s->left -= len;
|
||||
datalen -= len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(s->left == 0) {
|
||||
call(s, WEBSOCKET_DATA_RECEIVED, NULL, s->len);
|
||||
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
|
||||
|
||||
/* Need to keep parsing the incoming data to check for more
|
||||
frames, if the incoming datalen is > than s->left. */
|
||||
if(datalen > 0) {
|
||||
PRINTF("XXX 1 again\n");
|
||||
websocket_http_client_datahandler(client_state,
|
||||
data, datalen);
|
||||
}
|
||||
}
|
||||
} else if(s->state == WEBSOCKET_STATE_RECEIVING_DATA) {
|
||||
/* XXX todo: mask if needed. */
|
||||
/* PRINTF("Calling with s->left %d datalen %d\n",
|
||||
s->left, datalen);*/
|
||||
if(datalen > 0) {
|
||||
if(datalen < s->left) {
|
||||
call(s, WEBSOCKET_DATA, data, datalen);
|
||||
s->left -= datalen;
|
||||
data += datalen;
|
||||
datalen = 0;
|
||||
} else {
|
||||
call(s, WEBSOCKET_DATA, data, s->left);
|
||||
data += s->left;
|
||||
datalen -= s->left;
|
||||
s->left = 0;
|
||||
}
|
||||
}
|
||||
if(s->left == 0) {
|
||||
call(s, WEBSOCKET_DATA_RECEIVED, NULL, s->len);
|
||||
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
|
||||
/* Need to keep parsing the incoming data to check for more
|
||||
frames, if the incoming datalen is > than len. */
|
||||
if(datalen > 0) {
|
||||
PRINTF("XXX 2 again (datalen %d s->left %d)\n", datalen, (int)s->left);
|
||||
websocket_http_client_datahandler(client_state,
|
||||
data, datalen);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
static uint8_t inited = 0;
|
||||
if(!inited) {
|
||||
process_start(&websocket_process, NULL);
|
||||
list_init(websocketlist);
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
websocket_init(struct websocket *s)
|
||||
{
|
||||
init();
|
||||
websocket_http_client_init(&s->s);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
websocket_set_proxy(struct websocket *s,
|
||||
const uip_ipaddr_t *addr, uint16_t port)
|
||||
{
|
||||
websocket_http_client_set_proxy(&s->s, addr, port);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
websocket_result_t
|
||||
websocket_open(struct websocket *s, const char *url,
|
||||
const char *subprotocol, const char *hdr,
|
||||
websocket_callback c)
|
||||
{
|
||||
int ret;
|
||||
char host[MAX_HOSTLEN];
|
||||
char path[MAX_PATHLEN];
|
||||
uint16_t port;
|
||||
uip_ipaddr_t addr;
|
||||
|
||||
init();
|
||||
|
||||
if(s == NULL) {
|
||||
return WEBSOCKET_ERR;
|
||||
}
|
||||
|
||||
if(s->state != WEBSOCKET_STATE_CLOSED) {
|
||||
PRINTF("websocket_open: closing websocket before opening it again.\n");
|
||||
websocket_close(s);
|
||||
}
|
||||
s->callback = c;
|
||||
|
||||
if(parse_url(url, host, &port, path)) {
|
||||
list_add(websocketlist, s);
|
||||
websocket_http_client_register(&s->s, host, port, path, subprotocol, hdr);
|
||||
|
||||
/* First check if the host is an IP address. */
|
||||
if(uiplib_ip4addrconv(host, (uip_ip4addr_t *)&addr) == 0 &&
|
||||
uiplib_ip6addrconv(host, (uip_ip6addr_t *)&addr) == 0) {
|
||||
/* Try to lookup the hostname. If it fails, we initiate a hostname
|
||||
lookup and print out an informative message on the
|
||||
statusbar. */
|
||||
ret = resolv_lookup(host, NULL);
|
||||
if(ret != RESOLV_STATUS_CACHED) {
|
||||
resolv_query(host);
|
||||
s->state = WEBSOCKET_STATE_DNS_REQUEST_SENT;
|
||||
PRINTF("Resolving host...\n");
|
||||
return WEBSOCKET_OK;
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_CONTEXT_BEGIN(&websocket_process);
|
||||
ret = start_get(s);
|
||||
PROCESS_CONTEXT_END();
|
||||
return ret;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
websocket_close(struct websocket *s)
|
||||
{
|
||||
websocket_http_client_close(&s->s);
|
||||
s->state = WEBSOCKET_STATE_CLOSED;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
send_data(struct websocket *s, const void *data,
|
||||
uint16_t datalen, uint8_t data_type_opcode)
|
||||
{
|
||||
uint8_t buf[WEBSOCKET_MAX_MSGLEN + 4 + 4]; /* The extra + 4 + 4 here
|
||||
comes from the size of
|
||||
the websocket framing
|
||||
header. */
|
||||
struct websocket_frame_hdr *hdr;
|
||||
struct websocket_frame_mask *mask;
|
||||
|
||||
PRINTF("websocket send data len %d %.*s\n", datalen, datalen, (char *)data);
|
||||
if(s->state == WEBSOCKET_STATE_CLOSED ||
|
||||
s->state == WEBSOCKET_STATE_DNS_REQUEST_SENT ||
|
||||
s->state == WEBSOCKET_STATE_HTTP_REQUEST_SENT) {
|
||||
/* Trying to send data on a non-connected websocket. */
|
||||
PRINTF("websocket send fail: not connected\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We need to have 4 + 4 additional bytes for the websocket framing
|
||||
header. */
|
||||
if(4 + 4 + datalen > websocket_http_client_sendbuflen(&s->s)) {
|
||||
PRINTF("websocket: too few bytes left (%d left, %d needed)\n",
|
||||
websocket_http_client_sendbuflen(&s->s),
|
||||
4 + 4 + datalen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(datalen > sizeof(buf) - 4 - 4) {
|
||||
PRINTF("websocket: trying to send too large data chunk %d > %d\n",
|
||||
datalen, sizeof(buf) - 4 - 4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr = (struct websocket_frame_hdr *)&buf[0];
|
||||
hdr->opcode = WEBSOCKET_FIN_BIT | data_type_opcode;
|
||||
|
||||
/* If the datalen is larger than 125 bytes, we need to send the data
|
||||
length as two bytes. If the data length would be larger than 64k,
|
||||
we should send the length as 4 bytes, but since we specify the
|
||||
datalen as an unsigned 16-bit int, we do not handle the 64k case
|
||||
here. */
|
||||
if(datalen > 125) {
|
||||
/* Data from client must always have the mask bit set, and a data
|
||||
mask sent right after the header. */
|
||||
hdr->len = 126 | WEBSOCKET_MASK_BIT;
|
||||
hdr->extlen[0] = datalen >> 8;
|
||||
hdr->extlen[1] = datalen & 0xff;
|
||||
|
||||
mask = (struct websocket_frame_mask *)&buf[4];
|
||||
mask->mask[0] =
|
||||
mask->mask[1] =
|
||||
mask->mask[2] =
|
||||
mask->mask[3] = 0;
|
||||
memcpy(&buf[8], data, datalen);
|
||||
return websocket_http_client_send(&s->s, buf, 8 + datalen);
|
||||
} else {
|
||||
/* Data from client must always have the mask bit set, and a data
|
||||
mask sent right after the header. */
|
||||
hdr->len = datalen | WEBSOCKET_MASK_BIT;
|
||||
|
||||
mask = (struct websocket_frame_mask *)&buf[2];
|
||||
mask->mask[0] =
|
||||
mask->mask[1] =
|
||||
mask->mask[2] =
|
||||
mask->mask[3] = 0;
|
||||
memcpy(&buf[6], data, datalen);
|
||||
return websocket_http_client_send(&s->s, buf, 6 + datalen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_send_str(struct websocket *s, const char *str)
|
||||
{
|
||||
return send_data(s, str, strlen(str), WEBSOCKET_OPCODE_TEXT);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_send(struct websocket *s, const uint8_t *data,
|
||||
uint16_t datalen)
|
||||
{
|
||||
return send_data(s, data, datalen, WEBSOCKET_OPCODE_BIN);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_ping(struct websocket *s)
|
||||
{
|
||||
uint8_t buf[sizeof(struct websocket_frame_hdr) +
|
||||
sizeof(struct websocket_frame_mask)];
|
||||
struct websocket_frame_hdr *hdr;
|
||||
struct websocket_frame_mask *mask;
|
||||
|
||||
/* We need 2 + 4 additional bytes for the websocket framing
|
||||
header. */
|
||||
if(2 + 4 > websocket_http_client_sendbuflen(&s->s)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr = (struct websocket_frame_hdr *)&buf[0];
|
||||
mask = (struct websocket_frame_mask *)&buf[2];
|
||||
hdr->opcode = WEBSOCKET_FIN_BIT | WEBSOCKET_OPCODE_PING;
|
||||
|
||||
/* Data from client must always have the mask bit set, and a data
|
||||
mask sent right after the header. */
|
||||
hdr->len = 0 | WEBSOCKET_MASK_BIT;
|
||||
|
||||
/* XXX: We just set a dummy mask of 0 for now and hope that this
|
||||
works. */
|
||||
mask->mask[0] =
|
||||
mask->mask[1] =
|
||||
mask->mask[2] =
|
||||
mask->mask[3] = 0;
|
||||
websocket_http_client_send(&s->s, buf, 2 + 4);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
websocket_queuelen(struct websocket *s)
|
||||
{
|
||||
return websocket_http_client_queuelen(&s->s);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
113
core/net/ipv6/websocket.h
Normal file
113
core/net/ipv6/websocket.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
|
||||
* 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.
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef WEBSOCKET_H
|
||||
#define WEBSOCKET_H
|
||||
|
||||
#include "websocket-http-client.h"
|
||||
|
||||
typedef enum {
|
||||
WEBSOCKET_ERR = 0,
|
||||
WEBSOCKET_OK = 1,
|
||||
WEBSOCKET_IN_PROGRESS = 2,
|
||||
WEBSOCKET_HOSTNAME_NOT_FOUND = 3,
|
||||
WEBSOCKET_CONNECTED = 4,
|
||||
WEBSOCKET_DATA = 5,
|
||||
WEBSOCKET_RESET = 6,
|
||||
WEBSOCKET_TIMEDOUT = 7,
|
||||
WEBSOCKET_CLOSED = 8,
|
||||
WEBSOCKET_PINGED = 9,
|
||||
WEBSOCKET_DATA_RECEIVED = 10,
|
||||
WEBSOCKET_PONG_RECEIVED = 11,
|
||||
} websocket_result_t;
|
||||
|
||||
struct websocket;
|
||||
|
||||
typedef void (* websocket_callback)(struct websocket *s,
|
||||
websocket_result_t result,
|
||||
const uint8_t *data,
|
||||
uint16_t datalen);
|
||||
#ifdef WEBSOCKET_CONF_MAX_MSGLEN
|
||||
#define WEBSOCKET_MAX_MSGLEN WEBSOCKET_CONF_MAX_MSGLEN
|
||||
#else /* WEBSOCKET_CONF_MAX_MSGLEN */
|
||||
#define WEBSOCKET_MAX_MSGLEN 200
|
||||
#endif /* WEBSOCKET_CONF_MAX_MSGLEN */
|
||||
|
||||
struct websocket {
|
||||
struct websocket *next; /* Must be first. */
|
||||
struct websocket_http_client_state s;
|
||||
websocket_callback callback;
|
||||
|
||||
uint8_t mask[4];
|
||||
uint32_t left, len;
|
||||
uint8_t opcode;
|
||||
|
||||
uint8_t state;
|
||||
|
||||
uint8_t headercacheptr;
|
||||
uint8_t headercache[10]; /* The maximum websocket header + mask is 6
|
||||
+ 4 bytes long */
|
||||
};
|
||||
|
||||
enum {
|
||||
WEBSOCKET_STATE_CLOSED = 0,
|
||||
WEBSOCKET_STATE_DNS_REQUEST_SENT = 1,
|
||||
WEBSOCKET_STATE_HTTP_REQUEST_SENT = 2,
|
||||
WEBSOCKET_STATE_WAITING_FOR_HEADER = 3,
|
||||
WEBSOCKET_STATE_RECEIVING_HEADER = 4,
|
||||
WEBSOCKET_STATE_HEADER_RECEIVED = 5,
|
||||
WEBSOCKET_STATE_RECEIVING_DATA = 6,
|
||||
};
|
||||
|
||||
|
||||
void websocket_init(struct websocket *s);
|
||||
|
||||
void websocket_set_proxy(struct websocket *s,
|
||||
const uip_ipaddr_t *addr, uint16_t port);
|
||||
|
||||
websocket_result_t websocket_open(struct websocket *s,
|
||||
const char *url,
|
||||
const char *subprotocol,
|
||||
const char *hdr,
|
||||
websocket_callback c);
|
||||
|
||||
int websocket_send(struct websocket *s,
|
||||
const uint8_t *data, uint16_t datalen);
|
||||
|
||||
int websocket_send_str(struct websocket *s,
|
||||
const char *strptr);
|
||||
|
||||
void websocket_close(struct websocket *s);
|
||||
|
||||
int websocket_ping(struct websocket *s);
|
||||
|
||||
int websocket_queuelen(struct websocket *s);
|
||||
|
||||
#endif /* WEBSOCKET_H */
|
|
@ -51,7 +51,7 @@
|
|||
/* Maximum value for the freshness counter */
|
||||
#define FRESHNESS_MAX 16
|
||||
/* Statistics with no update in FRESHNESS_EXPIRATION_TIMEOUT is not fresh */
|
||||
#define FRESHNESS_EXPIRATION_TIME (10 * 60 * CLOCK_SECOND)
|
||||
#define FRESHNESS_EXPIRATION_TIME (10 * 60 * (clock_time_t)CLOCK_SECOND)
|
||||
|
||||
/* EWMA (exponential moving average) used to maintain statistics over time */
|
||||
#define EWMA_SCALE 100
|
||||
|
@ -206,6 +206,6 @@ void
|
|||
link_stats_init(void)
|
||||
{
|
||||
nbr_table_register(link_stats, NULL);
|
||||
ctimer_set(&periodic_timer, 60 * CLOCK_SECOND * FRESHNESS_HALF_LIFE,
|
||||
ctimer_set(&periodic_timer, 60 * (clock_time_t)CLOCK_SECOND * FRESHNESS_HALF_LIFE,
|
||||
periodic, NULL);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,9 @@ const linkaddr_t linkaddr_null = { { 0, 0 } };
|
|||
#if LINKADDR_SIZE == 8
|
||||
const linkaddr_t linkaddr_null = { { 0, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
#endif /*LINKADDR_SIZE == 8*/
|
||||
#if LINKADDR_SIZE == 6
|
||||
const linkaddr_t linkaddr_null = { { 0, 0, 0, 0, 0, 0 } };
|
||||
#endif /*LINKADDR_SIZE == 6*/
|
||||
#endif /*LINKADDR_SIZE == 2*/
|
||||
|
||||
|
||||
|
|
|
@ -207,13 +207,13 @@ static int we_are_receiving_burst = 0;
|
|||
#define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 2500
|
||||
#endif
|
||||
|
||||
/* AFTER_ACK_DETECTECT_WAIT_TIME is the time to wait after a potential
|
||||
/* AFTER_ACK_DETECTED_WAIT_TIME is the time to wait after a potential
|
||||
ACK packet has been detected until we can read it out from the
|
||||
radio. */
|
||||
#ifdef CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME
|
||||
#define AFTER_ACK_DETECTECT_WAIT_TIME CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME
|
||||
#ifdef CONTIKIMAC_CONF_AFTER_ACK_DETECTED_WAIT_TIME
|
||||
#define AFTER_ACK_DETECTED_WAIT_TIME CONTIKIMAC_CONF_AFTER_ACK_DETECTED_WAIT_TIME
|
||||
#else
|
||||
#define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1500
|
||||
#define AFTER_ACK_DETECTED_WAIT_TIME RTIMER_ARCH_SECOND / 1500
|
||||
#endif
|
||||
|
||||
/* MAX_PHASE_STROBE_TIME is the time that we transmit repeated packets
|
||||
|
@ -766,7 +766,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
|||
NETSTACK_RADIO.channel_clear() == 0)) {
|
||||
uint8_t ackbuf[ACK_LEN];
|
||||
wt = RTIMER_NOW();
|
||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
|
||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTED_WAIT_TIME)) { }
|
||||
|
||||
len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
|
||||
if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) {
|
||||
|
@ -878,6 +878,10 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
|||
if(next != NULL) {
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
|
||||
}
|
||||
#if !NETSTACK_CONF_BRIDGE_MODE
|
||||
/* If NETSTACK_CONF_BRIDGE_MODE is set, assume PACKETBUF_ADDR_SENDER is already set. */
|
||||
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
|
||||
#endif
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
|
||||
if(NETSTACK_FRAMER.create() < 0) {
|
||||
PRINTF("contikimac: framer failed\n");
|
||||
|
|
|
@ -231,10 +231,12 @@ tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n)
|
|||
mac_callback_t sent;
|
||||
struct qbuf_metadata *metadata;
|
||||
void *cptr;
|
||||
uint8_t ntx;
|
||||
|
||||
metadata = (struct qbuf_metadata *)q->ptr;
|
||||
sent = metadata->sent;
|
||||
cptr = metadata->cptr;
|
||||
ntx = n->transmissions;
|
||||
|
||||
switch(status) {
|
||||
case MAC_TX_OK:
|
||||
|
@ -251,7 +253,7 @@ tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n)
|
|||
}
|
||||
|
||||
free_packet(n, q, status);
|
||||
mac_call_sent_callback(sent, cptr, status, n->transmissions);
|
||||
mac_call_sent_callback(sent, cptr, status, ntx);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
|
|
@ -146,24 +146,45 @@ frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest
|
|||
}
|
||||
|
||||
if(fcf->frame_version == FRAME802154_IEEE802154E_2012) {
|
||||
/* IEEE 802.15.4e-2012, Table 2a, PAN ID Compression */
|
||||
if(!fcf->panid_compression) {
|
||||
if(fcf->dest_addr_mode) {
|
||||
/* Use destination PAN ID if destination address is present */
|
||||
/*
|
||||
* IEEE 802.15.4-2015
|
||||
* Table 7-2, PAN ID Compression value for frame version 0b10
|
||||
*/
|
||||
if((fcf->dest_addr_mode == FRAME802154_NOADDR &&
|
||||
fcf->src_addr_mode == FRAME802154_NOADDR &&
|
||||
fcf->panid_compression == 1) ||
|
||||
(fcf->dest_addr_mode != FRAME802154_NOADDR &&
|
||||
fcf->src_addr_mode == FRAME802154_NOADDR &&
|
||||
fcf->panid_compression == 0) ||
|
||||
(fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
|
||||
fcf->src_addr_mode == FRAME802154_LONGADDRMODE &&
|
||||
fcf->panid_compression == 0) ||
|
||||
((fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
|
||||
fcf->src_addr_mode != FRAME802154_NOADDR) ||
|
||||
(fcf->dest_addr_mode != FRAME802154_NOADDR &&
|
||||
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE)) ){
|
||||
dest_pan_id = 1;
|
||||
} else if(fcf->src_addr_mode) {
|
||||
/* Only src address, include src PAN ID */
|
||||
}
|
||||
|
||||
if(fcf->panid_compression == 0 &&
|
||||
((fcf->dest_addr_mode == FRAME802154_NOADDR &&
|
||||
fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
|
||||
(fcf->dest_addr_mode == FRAME802154_NOADDR &&
|
||||
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
|
||||
(fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
|
||||
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
|
||||
(fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
|
||||
fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
|
||||
(fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
|
||||
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE))) {
|
||||
src_pan_id = 1;
|
||||
}
|
||||
} else if((fcf->dest_addr_mode == 0) && (fcf->src_addr_mode == 0)) {
|
||||
/* No address included: PAN ID compression flag changes meaning */
|
||||
dest_pan_id = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* No PAN ID in ACK */
|
||||
if(fcf->frame_type != FRAME802154_ACKFRAME) {
|
||||
if(!fcf->panid_compression && fcf->src_addr_mode & 3) {
|
||||
/* If compressed, don't inclue source PAN ID */
|
||||
/* If compressed, don't include source PAN ID */
|
||||
src_pan_id = 1;
|
||||
}
|
||||
if(fcf->dest_addr_mode & 3) {
|
||||
|
|
|
@ -70,7 +70,7 @@ struct ieee802154_ies {
|
|||
uint16_t ie_mlme_len;
|
||||
/* Payload Short MLME IEs */
|
||||
uint8_t ie_tsch_synchronization_offset;
|
||||
struct asn_t ie_asn;
|
||||
struct tsch_asn_t ie_asn;
|
||||
uint8_t ie_join_priority;
|
||||
uint8_t ie_tsch_timeslot_id;
|
||||
uint16_t ie_tsch_timeslot[tsch_ts_elements_count];
|
||||
|
|
|
@ -173,7 +173,8 @@ create_frame(int type, int do_create)
|
|||
* Set up the source address using only the long address mode for
|
||||
* phase 1.
|
||||
*/
|
||||
linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr);
|
||||
linkaddr_copy((linkaddr_t *)¶ms.src_addr,
|
||||
packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||
|
||||
params.payload = packetbuf_dataptr();
|
||||
params.payload_len = packetbuf_datalen();
|
||||
|
|
|
@ -46,10 +46,10 @@
|
|||
#include "net/rime/rimestats.h"
|
||||
#include <string.h>
|
||||
|
||||
#if CONTIKI_TARGET_COOJA
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
#include "lib/simEnvChange.h"
|
||||
#include "sys/cooja_mt.h"
|
||||
#endif /* CONTIKI_TARGET_COOJA */
|
||||
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
|
@ -158,10 +158,10 @@ send_one_packet(mac_callback_t sent, void *ptr)
|
|||
wt = RTIMER_NOW();
|
||||
watchdog_periodic();
|
||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) {
|
||||
#if CONTIKI_TARGET_COOJA
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
simProcessRunValue = 1;
|
||||
cooja_mt_yield();
|
||||
#endif /* CONTIKI_TARGET_COOJA */
|
||||
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
|
||||
}
|
||||
|
||||
ret = MAC_TX_NOACK;
|
||||
|
@ -176,10 +176,10 @@ send_one_packet(mac_callback_t sent, void *ptr)
|
|||
watchdog_periodic();
|
||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(),
|
||||
wt + AFTER_ACK_DETECTED_WAIT_TIME)) {
|
||||
#if CONTIKI_TARGET_COOJA
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
simProcessRunValue = 1;
|
||||
cooja_mt_yield();
|
||||
#endif /* CONTIKI_TARGET_COOJA */
|
||||
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ It has been tested on the following platforms:
|
|||
* Zolertia Zoul (`zoul`, tested on hardware)
|
||||
* OpenMote-CC2538 (`openmote-cc2538`, tested on hardware)
|
||||
* CC2650 (`srf06-cc26xx`, tested on hardware)
|
||||
* Cooja mote (`cooja`, tested with cooja)
|
||||
|
||||
This implementation was present at the ETSI Plugtest
|
||||
event in Prague in July 2015, and did successfully inter-operate with all
|
||||
|
@ -83,7 +84,7 @@ Orchestra is implemented in:
|
|||
|
||||
A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`.
|
||||
To use TSCH, first make sure your platform supports it.
|
||||
Currently, `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul`, `openmote-cc2538`, and `srf06-cc26xx` are the supported platforms.
|
||||
Currently, `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul`, `openmote-cc2538`, `srf06-cc26xx`, and `cooja` are the supported platforms.
|
||||
To add your own, we refer the reader to the next section.
|
||||
|
||||
To add TSCH to your application, first include the TSCH module from your makefile with:
|
||||
|
@ -179,7 +180,7 @@ Instead, TSCH will poll the driver for incoming packets, from interrupt, exactly
|
|||
|
||||
TSCH will check when initializing (in `tsch_init`) that the radio driver supports all required features, namely:
|
||||
* get and set Rx mode (`RADIO_PARAM_RX_MODE`) as follows:
|
||||
* enable address filtering with `RADIO_RX_MODE_ADDRESS_FILTER`
|
||||
* disable address filtering with `RADIO_RX_MODE_ADDRESS_FILTER`
|
||||
* disable auto-ack with `RADIO_RX_MODE_AUTOACK`
|
||||
* enable poll mode with `RADIO_RX_MODE_POLL_MODE`
|
||||
* get and set Tx mode (`RADIO_PARAM_TX_MODE`) as follows:
|
||||
|
|
|
@ -38,8 +38,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "tsch-adaptive-timesync.h"
|
||||
#include "tsch-log.h"
|
||||
#include "net/mac/tsch/tsch.h"
|
||||
#include "net/mac/tsch/tsch-conf.h"
|
||||
#include "net/mac/tsch/tsch-adaptive-timesync.h"
|
||||
#include "net/mac/tsch/tsch-log.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if TSCH_ADAPTIVE_TIMESYNC
|
||||
|
@ -72,6 +74,10 @@ timesync_entry_add(int32_t val, uint32_t time_delta)
|
|||
buffer[pos] = val;
|
||||
if(timesync_entry_count < NUM_TIMESYNC_ENTRIES) {
|
||||
timesync_entry_count++;
|
||||
} else {
|
||||
/* We now have accurate drift compensation.
|
||||
* Increase keep-alive timeout. */
|
||||
tsch_set_ka_timeout(TSCH_MAX_KEEPALIVE_TIMEOUT);
|
||||
}
|
||||
pos = (pos + 1) % NUM_TIMESYNC_ENTRIES;
|
||||
|
||||
|
|
|
@ -44,13 +44,13 @@
|
|||
/************ Types ***********/
|
||||
|
||||
/* The ASN is an absolute slot number over 5 bytes. */
|
||||
struct asn_t {
|
||||
struct tsch_asn_t {
|
||||
uint32_t ls4b; /* least significant 4 bytes */
|
||||
uint8_t ms1b; /* most significant 1 byte */
|
||||
};
|
||||
|
||||
/* For quick modulo operation on ASN */
|
||||
struct asn_divisor_t {
|
||||
struct tsch_asn_divisor_t {
|
||||
uint16_t val; /* Divisor value */
|
||||
uint16_t asn_ms1b_remainder; /* Remainder of the operation 0x100000000 / val */
|
||||
};
|
||||
|
@ -58,38 +58,38 @@ struct asn_divisor_t {
|
|||
/************ Macros **********/
|
||||
|
||||
/* Initialize ASN */
|
||||
#define ASN_INIT(asn, ms1b_, ls4b_) do { \
|
||||
#define TSCH_ASN_INIT(asn, ms1b_, ls4b_) do { \
|
||||
(asn).ms1b = (ms1b_); \
|
||||
(asn).ls4b = (ls4b_); \
|
||||
} while(0);
|
||||
|
||||
/* Increment an ASN by inc (32 bits) */
|
||||
#define ASN_INC(asn, inc) do { \
|
||||
#define TSCH_ASN_INC(asn, inc) do { \
|
||||
uint32_t new_ls4b = (asn).ls4b + (inc); \
|
||||
if(new_ls4b < (asn).ls4b) { (asn).ms1b++; } \
|
||||
(asn).ls4b = new_ls4b; \
|
||||
} while(0);
|
||||
|
||||
/* Decrement an ASN by inc (32 bits) */
|
||||
#define ASN_DEC(asn, dec) do { \
|
||||
#define TSCH_ASN_DEC(asn, dec) do { \
|
||||
uint32_t new_ls4b = (asn).ls4b - (dec); \
|
||||
if(new_ls4b > (asn).ls4b) { (asn).ms1b--; } \
|
||||
(asn).ls4b = new_ls4b; \
|
||||
} while(0);
|
||||
|
||||
/* Returns the 32-bit diff between asn1 and asn2 */
|
||||
#define ASN_DIFF(asn1, asn2) \
|
||||
#define TSCH_ASN_DIFF(asn1, asn2) \
|
||||
((asn1).ls4b - (asn2).ls4b)
|
||||
|
||||
/* Initialize a struct asn_divisor_t */
|
||||
#define ASN_DIVISOR_INIT(div, val_) do { \
|
||||
#define TSCH_ASN_DIVISOR_INIT(div, val_) do { \
|
||||
(div).val = (val_); \
|
||||
(div).asn_ms1b_remainder = ((0xffffffff % (val_)) + 1) % (val_); \
|
||||
} while(0);
|
||||
|
||||
/* Returns the result (16 bits) of a modulo operation on ASN,
|
||||
* with divisor being a struct asn_divisor_t */
|
||||
#define ASN_MOD(asn, div) \
|
||||
#define TSCH_ASN_MOD(asn, div) \
|
||||
((uint16_t)((asn).ls4b % (div).val) \
|
||||
+ (uint16_t)((asn).ms1b * (div).asn_ms1b_remainder % (div).val)) \
|
||||
% (div).val
|
||||
|
|
|
@ -174,7 +174,7 @@
|
|||
#ifdef TSCH_CONF_ADAPTIVE_TIMESYNC
|
||||
#define TSCH_ADAPTIVE_TIMESYNC TSCH_CONF_ADAPTIVE_TIMESYNC
|
||||
#else
|
||||
#define TSCH_ADAPTIVE_TIMESYNC 0
|
||||
#define TSCH_ADAPTIVE_TIMESYNC 1
|
||||
#endif
|
||||
|
||||
/* HW frame filtering enabled */
|
||||
|
|
|
@ -132,7 +132,7 @@ tsch_log_prepare_add(void)
|
|||
int log_index = ringbufindex_peek_put(&log_ringbuf);
|
||||
if(log_index != -1) {
|
||||
struct tsch_log_t *log = &log_array[log_index];
|
||||
log->asn = current_asn;
|
||||
log->asn = tsch_current_asn;
|
||||
log->link = current_link;
|
||||
return log;
|
||||
} else {
|
||||
|
|
|
@ -81,7 +81,7 @@ struct tsch_log_t {
|
|||
tsch_log_rx,
|
||||
tsch_log_message
|
||||
} type;
|
||||
struct asn_t asn;
|
||||
struct tsch_asn_t asn;
|
||||
struct tsch_link *link;
|
||||
union {
|
||||
char message[48];
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
/* Construct enhanced ACK packet and return ACK length */
|
||||
int
|
||||
tsch_packet_create_eack(uint8_t *buf, int buf_size,
|
||||
linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack)
|
||||
const linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack)
|
||||
{
|
||||
int ret;
|
||||
uint8_t curr_len = 0;
|
||||
|
@ -338,7 +338,7 @@ int
|
|||
tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offset)
|
||||
{
|
||||
struct ieee802154_ies ies;
|
||||
ies.ie_asn = current_asn;
|
||||
ies.ie_asn = tsch_current_asn;
|
||||
ies.ie_join_priority = tsch_join_priority;
|
||||
frame80215e_create_ie_tsch_synchronization(buf+tsch_sync_ie_offset, buf_size-tsch_sync_ie_offset, &ies);
|
||||
return 1;
|
||||
|
|
|
@ -88,7 +88,7 @@ by default, useful in case of duplicate seqno */
|
|||
|
||||
/* Construct enhanced ACK packet and return ACK length */
|
||||
int tsch_packet_create_eack(uint8_t *buf, int buf_size,
|
||||
linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack);
|
||||
const linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack);
|
||||
/* Parse enhanced ACK packet, extract drift and nack */
|
||||
int tsch_packet_parse_eack(const uint8_t *buf, int buf_size,
|
||||
uint8_t seqno, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len);
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
#include "net/linkaddr.h"
|
||||
#include "net/mac/tsch/tsch-asn.h"
|
||||
#include "net/mac/tsch/tsch-conf.h"
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
#include "lib/simEnvChange.h"
|
||||
#include "sys/cooja_mt.h"
|
||||
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
|
||||
|
||||
/************ Types ***********/
|
||||
|
||||
|
@ -76,12 +80,12 @@ extern const linkaddr_t tsch_broadcast_address;
|
|||
/* The address we use to identify EB queue */
|
||||
extern const linkaddr_t tsch_eb_address;
|
||||
/* The current Absolute Slot Number (ASN) */
|
||||
extern struct asn_t current_asn;
|
||||
extern struct tsch_asn_t tsch_current_asn;
|
||||
extern uint8_t tsch_join_priority;
|
||||
extern struct tsch_link *current_link;
|
||||
/* TSCH channel hopping sequence */
|
||||
extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
|
||||
extern struct asn_divisor_t tsch_hopping_sequence_length;
|
||||
extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
|
||||
/* TSCH timeslot timing (in rtimer ticks) */
|
||||
extern rtimer_clock_t tsch_timing[tsch_ts_elements_count];
|
||||
|
||||
|
@ -109,7 +113,14 @@ void tsch_disassociate(void);
|
|||
#define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length)
|
||||
|
||||
/* Wait for a condition with timeout t0+offset. */
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
|
||||
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \
|
||||
simProcessRunValue = 1; \
|
||||
cooja_mt_yield(); \
|
||||
};
|
||||
#else
|
||||
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
|
||||
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ;
|
||||
|
||||
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
|
||||
#endif /* __TSCH_PRIVATE_H__ */
|
||||
|
|
|
@ -163,6 +163,13 @@ tsch_queue_update_time_source(const linkaddr_t *new_addr)
|
|||
/* Update time source */
|
||||
if(new_time_src != NULL) {
|
||||
new_time_src->is_time_source = 1;
|
||||
/* (Re)set keep-alive timeout */
|
||||
tsch_set_ka_timeout(TSCH_KEEPALIVE_TIMEOUT);
|
||||
/* Start sending keepalives */
|
||||
tsch_schedule_keepalive();
|
||||
} else {
|
||||
/* Stop sending keepalives */
|
||||
tsch_set_ka_timeout(0);
|
||||
}
|
||||
|
||||
if(old_time_src != NULL) {
|
||||
|
|
|
@ -85,7 +85,7 @@ tsch_rpl_callback_new_dio_interval(uint8_t dio_interval)
|
|||
tsch_set_coordinator(1);
|
||||
}
|
||||
/* Set EB period */
|
||||
tsch_set_eb_period(TSCH_EB_PERIOD);
|
||||
tsch_set_eb_period((CLOCK_SECOND * 1UL << dag->instance->dio_intcurrent) / 1000);
|
||||
/* Set join priority based on RPL rank */
|
||||
tsch_set_join_priority(DAG_RANK(dag->rank, dag->instance) - 1);
|
||||
} else {
|
||||
|
|
|
@ -87,7 +87,7 @@ tsch_schedule_add_slotframe(uint16_t handle, uint16_t size)
|
|||
if(sf != NULL) {
|
||||
/* Initialize the slotframe */
|
||||
sf->handle = handle;
|
||||
ASN_DIVISOR_INIT(sf->size, size);
|
||||
TSCH_ASN_DIVISOR_INIT(sf->size, size);
|
||||
LIST_STRUCT_INIT(sf, links_list);
|
||||
/* Add the slotframe to the global list */
|
||||
list_add(slotframe_list, sf);
|
||||
|
@ -310,7 +310,7 @@ tsch_schedule_get_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t ti
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */
|
||||
struct tsch_link *
|
||||
tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset,
|
||||
tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset,
|
||||
struct tsch_link **backup_link)
|
||||
{
|
||||
uint16_t time_to_curr_best = 0;
|
||||
|
@ -324,7 +324,7 @@ tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset,
|
|||
/* For each slotframe, look for the earliest occurring link */
|
||||
while(sf != NULL) {
|
||||
/* Get timeslot from ASN, given the slotframe length */
|
||||
uint16_t timeslot = ASN_MOD(*asn, sf->size);
|
||||
uint16_t timeslot = TSCH_ASN_MOD(*asn, sf->size);
|
||||
struct tsch_link *l = list_head(sf->links_list);
|
||||
while(l != NULL) {
|
||||
uint16_t time_to_timeslot =
|
||||
|
|
|
@ -119,7 +119,7 @@ struct tsch_slotframe {
|
|||
uint16_t handle;
|
||||
/* Number of timeslots in the slotframe.
|
||||
* Stored as struct asn_divisor_t because we often need ASN%size */
|
||||
struct asn_divisor_t size;
|
||||
struct tsch_asn_divisor_t size;
|
||||
/* List of links belonging to this slotframe */
|
||||
LIST_STRUCT(links_list);
|
||||
};
|
||||
|
@ -158,7 +158,7 @@ int tsch_schedule_remove_link(struct tsch_slotframe *slotframe, struct tsch_link
|
|||
int tsch_schedule_remove_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot);
|
||||
|
||||
/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */
|
||||
struct tsch_link * tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset,
|
||||
struct tsch_link * tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset,
|
||||
struct tsch_link **backup_link);
|
||||
|
||||
#endif /* __TSCH_SCHEDULE_H__ */
|
||||
|
|
|
@ -73,7 +73,7 @@ static aes_key keys[] = {
|
|||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
tsch_security_init_nonce(uint8_t *nonce,
|
||||
const linkaddr_t *sender, struct asn_t *asn)
|
||||
const linkaddr_t *sender, struct tsch_asn_t *asn)
|
||||
{
|
||||
memcpy(nonce, sender, 8);
|
||||
nonce[8] = asn->ms1b;
|
||||
|
@ -120,11 +120,12 @@ tsch_security_check_level(const frame802154_t *frame)
|
|||
required_key_index = TSCH_SECURITY_KEY_INDEX_OTHER;
|
||||
break;
|
||||
}
|
||||
return frame->aux_hdr.security_control.security_level == required_security_level
|
||||
&& frame->aux_hdr.key_index == required_key_index;
|
||||
return ((frame->aux_hdr.security_control.security_level ==
|
||||
required_security_level) &&
|
||||
frame->aux_hdr.key_index == required_key_index);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
unsigned int
|
||||
tsch_security_mic_len(const frame802154_t *frame)
|
||||
{
|
||||
if(frame != NULL && frame->fcf.security_enabled) {
|
||||
|
@ -134,9 +135,9 @@ tsch_security_mic_len(const frame802154_t *frame)
|
|||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
unsigned int
|
||||
tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
|
||||
int hdrlen, int datalen, struct asn_t *asn)
|
||||
int hdrlen, int datalen, struct tsch_asn_t *asn)
|
||||
{
|
||||
frame802154_t frame;
|
||||
uint8_t key_index = 0;
|
||||
|
@ -159,7 +160,7 @@ tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
|
|||
|
||||
if(!frame.fcf.security_enabled) {
|
||||
/* Security is not enabled for this frame, we're done */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read security key index */
|
||||
|
@ -192,15 +193,15 @@ tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
|
|||
CCM_STAR.aead(nonce,
|
||||
outbuf + a_len, m_len,
|
||||
outbuf, a_len,
|
||||
outbuf + hdrlen + datalen, mic_len, 1
|
||||
);
|
||||
outbuf + hdrlen + datalen, mic_len, 1);
|
||||
|
||||
return mic_len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
unsigned int
|
||||
tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
|
||||
const frame802154_t *frame, const linkaddr_t *sender, struct asn_t *asn)
|
||||
const frame802154_t *frame, const linkaddr_t *sender,
|
||||
struct tsch_asn_t *asn)
|
||||
{
|
||||
uint8_t generated_mic[16];
|
||||
uint8_t key_index = 0;
|
||||
|
@ -250,8 +251,7 @@ tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
|
|||
CCM_STAR.aead(nonce,
|
||||
(uint8_t *)hdr + a_len, m_len,
|
||||
(uint8_t *)hdr, a_len,
|
||||
generated_mic, mic_len, 0
|
||||
);
|
||||
generated_mic, mic_len, 0);
|
||||
|
||||
if(mic_len > 0 && memcmp(generated_mic, hdr + hdrlen + datalen, mic_len) != 0) {
|
||||
return 0;
|
||||
|
|
|
@ -118,11 +118,28 @@
|
|||
typedef uint8_t aes_key[16];
|
||||
|
||||
/********** Functions *********/
|
||||
/**
|
||||
* \brief Return MIC length
|
||||
* \return The length of MIC (>= 0)
|
||||
*/
|
||||
unsigned int tsch_security_mic_len(const frame802154_t *frame);
|
||||
|
||||
int tsch_security_mic_len(const frame802154_t *frame);
|
||||
int tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
|
||||
int hdrlen, int datalen, struct asn_t *asn);
|
||||
int tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
|
||||
const frame802154_t *frame, const linkaddr_t *sender, struct asn_t *asn);
|
||||
/**
|
||||
* \brief Protect a frame with encryption and/or MIC
|
||||
* \return The length of a generated MIC (>= 0)
|
||||
*/
|
||||
unsigned int tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
|
||||
int hdrlen, int datalen,
|
||||
struct tsch_asn_t *asn);
|
||||
|
||||
/**
|
||||
* \brief Parse and check a frame protected with encryption and/or MIC
|
||||
* \retval 0 On error or security check failure (insecure frame)
|
||||
* \retval 1 On success or no need for security check (good frame)
|
||||
*/
|
||||
unsigned int tsch_security_parse_frame(const uint8_t *hdr, int hdrlen,
|
||||
int datalen, const frame802154_t *frame,
|
||||
const linkaddr_t *sender,
|
||||
struct tsch_asn_t *asn);
|
||||
|
||||
#endif /* __TSCH_SECURITY_H__ */
|
||||
|
|
|
@ -54,6 +54,10 @@
|
|||
#include "net/mac/tsch/tsch-packet.h"
|
||||
#include "net/mac/tsch/tsch-security.h"
|
||||
#include "net/mac/tsch/tsch-adaptive-timesync.h"
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
#include "lib/simEnvChange.h"
|
||||
#include "sys/cooja_mt.h"
|
||||
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
|
||||
|
||||
#if TSCH_LOG_LEVEL >= 1
|
||||
#define DEBUG DEBUG_PRINT
|
||||
|
@ -104,7 +108,10 @@
|
|||
#if RTIMER_SECOND < (32 * 1024)
|
||||
#error "TSCH: RTIMER_SECOND < (32 * 1024)"
|
||||
#endif
|
||||
#if RTIMER_SECOND >= 200000
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
/* Use 0 usec guard time for Cooja Mote with a 1 MHz Rtimer*/
|
||||
#define RTIMER_GUARD 0u
|
||||
#elif RTIMER_SECOND >= 200000
|
||||
#define RTIMER_GUARD (RTIMER_SECOND / 100000)
|
||||
#else
|
||||
#define RTIMER_GUARD 2u
|
||||
|
@ -132,7 +139,7 @@ struct ringbufindex input_ringbuf;
|
|||
struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
|
||||
|
||||
/* Last time we received Sync-IE (ACK or data packet from a time source) */
|
||||
static struct asn_t last_sync_asn;
|
||||
static struct tsch_asn_t last_sync_asn;
|
||||
|
||||
/* A global lock for manipulating data structures safely from outside of interrupt */
|
||||
static volatile int tsch_locked = 0;
|
||||
|
@ -200,7 +207,12 @@ tsch_get_lock(void)
|
|||
if(tsch_in_slot_operation) {
|
||||
busy_wait = 1;
|
||||
busy_wait_time = RTIMER_NOW();
|
||||
while(tsch_in_slot_operation);
|
||||
while(tsch_in_slot_operation) {
|
||||
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
|
||||
simProcessRunValue = 1;
|
||||
cooja_mt_yield();
|
||||
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
|
||||
}
|
||||
busy_wait_time = RTIMER_NOW() - busy_wait_time;
|
||||
}
|
||||
if(!tsch_locked) {
|
||||
|
@ -236,9 +248,9 @@ tsch_release_lock(void)
|
|||
|
||||
/* Return channel from ASN and channel offset */
|
||||
uint8_t
|
||||
tsch_calculate_channel(struct asn_t *asn, uint8_t channel_offset)
|
||||
tsch_calculate_channel(struct tsch_asn_t *asn, uint8_t channel_offset)
|
||||
{
|
||||
uint16_t index_of_0 = ASN_MOD(*asn, tsch_hopping_sequence_length);
|
||||
uint16_t index_of_0 = TSCH_ASN_MOD(*asn, tsch_hopping_sequence_length);
|
||||
uint16_t index_of_offset = (index_of_0 + channel_offset) % tsch_hopping_sequence_length.val;
|
||||
return tsch_hopping_sequence[index_of_offset];
|
||||
}
|
||||
|
@ -518,7 +530,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
* the original untouched. This is to allow for future retransmissions. */
|
||||
int with_encryption = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL) & 0x4;
|
||||
packet_len += tsch_security_secure_frame(packet, with_encryption ? encrypted_packet : packet, current_packet->header_len,
|
||||
packet_len - current_packet->header_len, ¤t_asn);
|
||||
packet_len - current_packet->header_len, &tsch_current_asn);
|
||||
if(with_encryption) {
|
||||
packet = encrypted_packet;
|
||||
}
|
||||
|
@ -615,7 +627,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
#if LLSEC802154_ENABLED
|
||||
if(ack_len != 0) {
|
||||
if(!tsch_security_parse_frame(ackbuf, ack_hdrlen, ack_len - ack_hdrlen - tsch_security_mic_len(&frame),
|
||||
&frame, ¤t_neighbor->addr, ¤t_asn)) {
|
||||
&frame, ¤t_neighbor->addr, &tsch_current_asn)) {
|
||||
TSCH_LOG_ADD(tsch_log_message,
|
||||
snprintf(log->message, sizeof(log->message),
|
||||
"!failed to authenticate ACK"));
|
||||
|
@ -632,7 +644,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
if(ack_len != 0) {
|
||||
if(is_time_source) {
|
||||
int32_t eack_time_correction = US_TO_RTIMERTICKS(ack_ies.ie_time_correction);
|
||||
int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn);
|
||||
int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
|
||||
if(eack_time_correction > SYNC_IE_BOUND) {
|
||||
drift_correction = SYNC_IE_BOUND;
|
||||
} else if(eack_time_correction < -SYNC_IE_BOUND) {
|
||||
|
@ -649,7 +661,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
is_drift_correction_used = 1;
|
||||
tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction);
|
||||
/* Keep track of sync time */
|
||||
last_sync_asn = current_asn;
|
||||
last_sync_asn = tsch_current_asn;
|
||||
tsch_schedule_keepalive();
|
||||
}
|
||||
mac_tx_status = MAC_TX_OK;
|
||||
|
@ -781,7 +793,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
/* Read packet */
|
||||
current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN);
|
||||
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
|
||||
current_input->rx_asn = current_asn;
|
||||
current_input->rx_asn = tsch_current_asn;
|
||||
current_input->rssi = (signed)radio_last_rssi;
|
||||
current_input->channel = current_channel;
|
||||
header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
|
||||
|
@ -801,7 +813,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
if(frame_valid) {
|
||||
if(tsch_security_parse_frame(
|
||||
current_input->payload, header_len, current_input->len - header_len - tsch_security_mic_len(&frame),
|
||||
&frame, &source_address, ¤t_asn)) {
|
||||
&frame, &source_address, &tsch_current_asn)) {
|
||||
current_input->len -= tsch_security_mic_len(&frame);
|
||||
} else {
|
||||
TSCH_LOG_ADD(tsch_log_message,
|
||||
|
@ -849,10 +861,11 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
ack_len = tsch_packet_create_eack(ack_buf, sizeof(ack_buf),
|
||||
&source_address, frame.seq, (int16_t)RTIMERTICKS_TO_US(estimated_drift), do_nack);
|
||||
|
||||
if(ack_len > 0) {
|
||||
#if LLSEC802154_ENABLED
|
||||
if(tsch_is_pan_secured) {
|
||||
/* Secure ACK frame. There is only header and header IEs, therefore data len == 0. */
|
||||
ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, ¤t_asn);
|
||||
ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, &tsch_current_asn);
|
||||
}
|
||||
#endif /* LLSEC802154_ENABLED */
|
||||
|
||||
|
@ -866,13 +879,14 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
NETSTACK_RADIO.transmit(ack_len);
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the sender is a time source, proceed to clock drift compensation */
|
||||
n = tsch_queue_get_nbr(&source_address);
|
||||
if(n != NULL && n->is_time_source) {
|
||||
int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn);
|
||||
int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
|
||||
/* Keep track of last sync time */
|
||||
last_sync_asn = current_asn;
|
||||
last_sync_asn = tsch_current_asn;
|
||||
/* Save estimated drift */
|
||||
drift_correction = -estimated_drift;
|
||||
is_drift_correction_used = 1;
|
||||
|
@ -958,7 +972,7 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
|||
is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX);
|
||||
if(is_active_slot) {
|
||||
/* Hop channel */
|
||||
current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset);
|
||||
current_channel = tsch_calculate_channel(&tsch_current_asn, current_link->channel_offset);
|
||||
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
|
||||
/* Turn the radio on already here if configured so; necessary for radios with slow startup */
|
||||
tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT);
|
||||
|
@ -984,12 +998,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
|||
/* End of slot operation, schedule next slot or resynchronize */
|
||||
|
||||
/* Do we need to resynchronize? i.e., wait for EB again */
|
||||
if(!tsch_is_coordinator && (ASN_DIFF(current_asn, last_sync_asn) >
|
||||
if(!tsch_is_coordinator && (TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn) >
|
||||
(100 * TSCH_CLOCK_TO_SLOTS(TSCH_DESYNC_THRESHOLD / 100, tsch_timing[tsch_ts_timeslot_length])))) {
|
||||
TSCH_LOG_ADD(tsch_log_message,
|
||||
snprintf(log->message, sizeof(log->message),
|
||||
"! leaving the network, last sync %u",
|
||||
(unsigned)ASN_DIFF(current_asn, last_sync_asn));
|
||||
(unsigned)TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn));
|
||||
);
|
||||
last_timesource_neighbor = NULL;
|
||||
tsch_disassociate();
|
||||
|
@ -1011,14 +1025,14 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
|||
}
|
||||
|
||||
/* Get next active link */
|
||||
current_link = tsch_schedule_get_next_active_link(¤t_asn, ×lot_diff, &backup_link);
|
||||
current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, ×lot_diff, &backup_link);
|
||||
if(current_link == NULL) {
|
||||
/* There is no next link. Fall back to default
|
||||
* behavior: wake up at the next slot. */
|
||||
timeslot_diff = 1;
|
||||
}
|
||||
/* Update ASN */
|
||||
ASN_INC(current_asn, timeslot_diff);
|
||||
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
|
||||
/* Time to next wake up */
|
||||
time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length] + drift_correction;
|
||||
drift_correction = 0;
|
||||
|
@ -1049,14 +1063,14 @@ tsch_slot_operation_start(void)
|
|||
do {
|
||||
uint16_t timeslot_diff;
|
||||
/* Get next active link */
|
||||
current_link = tsch_schedule_get_next_active_link(¤t_asn, ×lot_diff, &backup_link);
|
||||
current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, ×lot_diff, &backup_link);
|
||||
if(current_link == NULL) {
|
||||
/* There is no next link. Fall back to default
|
||||
* behavior: wake up at the next slot. */
|
||||
timeslot_diff = 1;
|
||||
}
|
||||
/* Update ASN */
|
||||
ASN_INC(current_asn, timeslot_diff);
|
||||
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
|
||||
/* Time to next wake up */
|
||||
time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length];
|
||||
/* Update current slot start */
|
||||
|
@ -1068,11 +1082,11 @@ tsch_slot_operation_start(void)
|
|||
/* Start actual slot operation */
|
||||
void
|
||||
tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
|
||||
struct asn_t *next_slot_asn)
|
||||
struct tsch_asn_t *next_slot_asn)
|
||||
{
|
||||
current_slot_start = next_slot_start;
|
||||
current_asn = *next_slot_asn;
|
||||
last_sync_asn = current_asn;
|
||||
tsch_current_asn = *next_slot_asn;
|
||||
last_sync_asn = tsch_current_asn;
|
||||
current_link = NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -87,7 +87,7 @@ int TSCH_CALLBACK_DO_NACK(struct tsch_link *link, linkaddr_t *src, linkaddr_t *d
|
|||
/* Stores data about an incoming packet */
|
||||
struct input_packet {
|
||||
uint8_t payload[TSCH_PACKET_MAX_LEN]; /* Packet payload */
|
||||
struct asn_t rx_asn; /* ASN when the packet was received */
|
||||
struct tsch_asn_t rx_asn; /* ASN when the packet was received */
|
||||
int len; /* Packet len */
|
||||
int16_t rssi; /* RSSI for this packet */
|
||||
uint8_t channel; /* Channel we received the packet on */
|
||||
|
@ -107,7 +107,7 @@ extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
|
|||
/********** Functions *********/
|
||||
|
||||
/* Returns a 802.15.4 channel from an ASN and channel offset */
|
||||
uint8_t tsch_calculate_channel(struct asn_t *asn, uint8_t channel_offset);
|
||||
uint8_t tsch_calculate_channel(struct tsch_asn_t *asn, uint8_t channel_offset);
|
||||
/* Is TSCH locked? */
|
||||
int tsch_is_locked(void);
|
||||
/* Lock TSCH (no link operation) */
|
||||
|
@ -117,7 +117,7 @@ void tsch_release_lock(void);
|
|||
/* Set global time before starting slot operation,
|
||||
* with a rtimer time and an ASN */
|
||||
void tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
|
||||
struct asn_t *next_slot_asn);
|
||||
struct tsch_asn_t *next_slot_asn);
|
||||
/* Start actual slot operation */
|
||||
void tsch_slot_operation_start(void);
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ NBR_TABLE(struct eb_stat, eb_stats);
|
|||
|
||||
/* TSCH channel hopping sequence */
|
||||
uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
|
||||
struct asn_divisor_t tsch_hopping_sequence_length;
|
||||
struct tsch_asn_divisor_t tsch_hopping_sequence_length;
|
||||
|
||||
/* Default TSCH timeslot timing (in micro-second) */
|
||||
static const uint16_t tsch_default_timing_us[tsch_ts_elements_count] = {
|
||||
|
@ -131,7 +131,7 @@ int tsch_is_associated = 0;
|
|||
/* Is the PAN running link-layer security? */
|
||||
int tsch_is_pan_secured = LLSEC802154_ENABLED;
|
||||
/* The current Absolute Slot Number (ASN) */
|
||||
struct asn_t current_asn;
|
||||
struct tsch_asn_t tsch_current_asn;
|
||||
/* Device rank or join priority:
|
||||
* For PAN coordinator: 0 -- lower is better */
|
||||
uint8_t tsch_join_priority;
|
||||
|
@ -139,6 +139,8 @@ uint8_t tsch_join_priority;
|
|||
static uint8_t tsch_packet_seqno = 0;
|
||||
/* Current period for EB output */
|
||||
static clock_time_t tsch_current_eb_period;
|
||||
/* Current period for keepalive output */
|
||||
static clock_time_t tsch_current_ka_timeout;
|
||||
|
||||
/* timer for sending keepalive messages */
|
||||
static struct ctimer keepalive_timer;
|
||||
|
@ -175,9 +177,15 @@ tsch_set_join_priority(uint8_t jp)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
tsch_set_ka_timeout(uint32_t timeout)
|
||||
{
|
||||
tsch_current_ka_timeout = timeout;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
tsch_set_eb_period(uint32_t period)
|
||||
{
|
||||
tsch_current_eb_period = period;
|
||||
tsch_current_eb_period = MIN(period, TSCH_MAX_EB_PERIOD);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -194,7 +202,7 @@ tsch_reset(void)
|
|||
tsch_queue_update_time_source(NULL);
|
||||
/* Initialize global variables */
|
||||
tsch_join_priority = 0xff;
|
||||
ASN_INIT(current_asn, 0, 0);
|
||||
TSCH_ASN_INIT(tsch_current_asn, 0, 0);
|
||||
current_link = NULL;
|
||||
/* Reset timeslot timing to defaults */
|
||||
for(i = 0; i < tsch_ts_elements_count; i++) {
|
||||
|
@ -244,10 +252,10 @@ keepalive_send()
|
|||
void
|
||||
tsch_schedule_keepalive()
|
||||
{
|
||||
/* Pick a delay in the range [TSCH_KEEPALIVE_TIMEOUT*0.9, TSCH_KEEPALIVE_TIMEOUT[ */
|
||||
if(!tsch_is_coordinator && tsch_is_associated) {
|
||||
unsigned long delay = (TSCH_KEEPALIVE_TIMEOUT - TSCH_KEEPALIVE_TIMEOUT / 10)
|
||||
+ random_rand() % (TSCH_KEEPALIVE_TIMEOUT / 10);
|
||||
/* Pick a delay in the range [tsch_current_ka_timeout*0.9, tsch_current_ka_timeout[ */
|
||||
if(!tsch_is_coordinator && tsch_is_associated && tsch_current_ka_timeout > 0) {
|
||||
unsigned long delay = (tsch_current_ka_timeout - tsch_current_ka_timeout / 10)
|
||||
+ random_rand() % (tsch_current_ka_timeout / 10);
|
||||
ctimer_set(&keepalive_timer, delay, keepalive_send, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -302,7 +310,7 @@ eb_input(struct input_packet *current_input)
|
|||
/* Did the EB come from our time source? */
|
||||
if(n != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &n->addr)) {
|
||||
/* Check for ASN drift */
|
||||
int32_t asn_diff = ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
|
||||
int32_t asn_diff = TSCH_ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
|
||||
if(asn_diff != 0) {
|
||||
/* We disagree with our time source's ASN -- leave the network */
|
||||
PRINTF("TSCH:! ASN drifted by %ld, leaving the network\n", asn_diff);
|
||||
|
@ -393,7 +401,7 @@ tsch_start_coordinator(void)
|
|||
frame802154_set_pan_id(IEEE802154_PANID);
|
||||
/* Initialize hopping sequence as default */
|
||||
memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
|
||||
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
|
||||
TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
|
||||
#if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL
|
||||
tsch_schedule_create_minimal();
|
||||
#endif
|
||||
|
@ -402,10 +410,10 @@ tsch_start_coordinator(void)
|
|||
tsch_join_priority = 0;
|
||||
|
||||
PRINTF("TSCH: starting as coordinator, PAN ID %x, asn-%x.%lx\n",
|
||||
frame802154_get_pan_id(), current_asn.ms1b, current_asn.ls4b);
|
||||
frame802154_get_pan_id(), tsch_current_asn.ms1b, tsch_current_asn.ls4b);
|
||||
|
||||
/* Start slot operation */
|
||||
tsch_slot_operation_sync(RTIMER_NOW(), ¤t_asn);
|
||||
tsch_slot_operation_sync(RTIMER_NOW(), &tsch_current_asn);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Leave the TSCH network */
|
||||
|
@ -434,7 +442,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
current_asn = ies.ie_asn;
|
||||
tsch_current_asn = ies.ie_asn;
|
||||
tsch_join_priority = ies.ie_join_priority + 1;
|
||||
|
||||
#if TSCH_JOIN_SECURED_ONLY
|
||||
|
@ -447,7 +455,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
|
|||
#if LLSEC802154_ENABLED
|
||||
if(!tsch_security_parse_frame(input_eb->payload, hdrlen,
|
||||
input_eb->len - hdrlen - tsch_security_mic_len(&frame),
|
||||
&frame, (linkaddr_t*)&frame.src_addr, ¤t_asn)) {
|
||||
&frame, (linkaddr_t*)&frame.src_addr, &tsch_current_asn)) {
|
||||
PRINTF("TSCH:! parse_eb: failed to authenticate\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -486,11 +494,11 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
|
|||
/* TSCH hopping sequence */
|
||||
if(ies.ie_channel_hopping_sequence_id == 0) {
|
||||
memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
|
||||
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
|
||||
TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
|
||||
} else {
|
||||
if(ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) {
|
||||
memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len);
|
||||
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len);
|
||||
TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len);
|
||||
} else {
|
||||
PRINTF("TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len);
|
||||
return 0;
|
||||
|
@ -501,10 +509,10 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
|
|||
/* Divide by 4k and multiply again to avoid integer overflow */
|
||||
uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(clock_time() / 4096, tsch_timing_timeslot_length); /* Expected ASN based on our current time*/
|
||||
int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(CLOCK_SECOND, tsch_timing_timeslot_length);
|
||||
int32_t asn_diff = (int32_t)current_asn.ls4b - expected_asn;
|
||||
int32_t asn_diff = (int32_t)tsch_current_asn.ls4b - expected_asn;
|
||||
if(asn_diff > asn_threshold) {
|
||||
PRINTF("TSCH:! EB ASN rejected %lx %lx %ld\n",
|
||||
current_asn.ls4b, expected_asn, asn_diff);
|
||||
tsch_current_asn.ls4b, expected_asn, asn_diff);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -554,7 +562,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
|
|||
frame802154_set_pan_id(frame.src_pid);
|
||||
|
||||
/* Synchronize on EB */
|
||||
tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], ¤t_asn);
|
||||
tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], &tsch_current_asn);
|
||||
|
||||
/* Update global flags */
|
||||
tsch_is_associated = 1;
|
||||
|
@ -570,7 +578,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
|
|||
PRINTF("TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ",
|
||||
tsch_is_pan_secured,
|
||||
frame.src_pid,
|
||||
current_asn.ms1b, current_asn.ls4b, tsch_join_priority,
|
||||
tsch_current_asn.ms1b, tsch_current_asn.ls4b, tsch_join_priority,
|
||||
ies.ie_tsch_timeslot_id,
|
||||
ies.ie_channel_hopping_sequence_id,
|
||||
ies.ie_tsch_slotframe_and_link.slotframe_size,
|
||||
|
@ -601,7 +609,7 @@ PT_THREAD(tsch_scan(struct pt *pt))
|
|||
/* Time when we started scanning on current_channel */
|
||||
static clock_time_t current_channel_since;
|
||||
|
||||
ASN_INIT(current_asn, 0, 0);
|
||||
TSCH_ASN_INIT(tsch_current_asn, 0, 0);
|
||||
|
||||
etimer_set(&scan_timer, CLOCK_SECOND / TSCH_ASSOCIATION_POLL_FREQUENCY);
|
||||
current_channel_since = clock_time();
|
||||
|
@ -741,7 +749,7 @@ PROCESS_THREAD(tsch_send_eb_process, ev, data)
|
|||
#endif /* LLSEC802154_ENABLED */
|
||||
eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE,
|
||||
&hdr_len, &tsch_sync_ie_offset);
|
||||
if(eb_len != 0) {
|
||||
if(eb_len > 0) {
|
||||
struct tsch_packet *p;
|
||||
packetbuf_set_datalen(eb_len);
|
||||
/* Enqueue EB packet */
|
||||
|
@ -902,6 +910,15 @@ send_packet(mac_callback_t sent, void *ptr)
|
|||
|
||||
packet_count_before = tsch_queue_packet_count(addr);
|
||||
|
||||
#if !NETSTACK_CONF_BRIDGE_MODE
|
||||
/*
|
||||
* In the Contiki stack, the source address of a frame is set at the RDC
|
||||
* layer. Since TSCH doesn't use any RDC protocol and bypasses the layer to
|
||||
* transmit a frame, it should set the source address by itself.
|
||||
*/
|
||||
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
|
||||
#endif
|
||||
|
||||
if((hdr_len = NETSTACK_FRAMER.create()) < 0) {
|
||||
PRINTF("TSCH:! can't send packet due to framer error\n");
|
||||
ret = MAC_TX_ERR;
|
||||
|
|
|
@ -49,18 +49,33 @@
|
|||
#define TSCH_KEEPALIVE_TIMEOUT (12 * CLOCK_SECOND)
|
||||
#endif
|
||||
|
||||
/* With TSCH_ADAPTIVE_TIMESYNC enabled: keep-alive timeout used after reaching
|
||||
* accurate drift compensation. */
|
||||
#ifdef TSCH_CONF_MAX_KEEPALIVE_TIMEOUT
|
||||
#define TSCH_MAX_KEEPALIVE_TIMEOUT TSCH_CONF_MAX_KEEPALIVE_TIMEOUT
|
||||
#else
|
||||
#define TSCH_MAX_KEEPALIVE_TIMEOUT (60 * CLOCK_SECOND)
|
||||
#endif
|
||||
|
||||
/* Max time without synchronization before leaving the PAN */
|
||||
#ifdef TSCH_CONF_DESYNC_THRESHOLD
|
||||
#define TSCH_DESYNC_THRESHOLD TSCH_CONF_DESYNC_THRESHOLD
|
||||
#else
|
||||
#define TSCH_DESYNC_THRESHOLD (4 * TSCH_KEEPALIVE_TIMEOUT)
|
||||
#define TSCH_DESYNC_THRESHOLD (2 * TSCH_MAX_KEEPALIVE_TIMEOUT)
|
||||
#endif
|
||||
|
||||
/* Period between two consecutive EBs */
|
||||
#ifdef TSCH_CONF_EB_PERIOD
|
||||
#define TSCH_EB_PERIOD TSCH_CONF_EB_PERIOD
|
||||
#else
|
||||
#define TSCH_EB_PERIOD (4 * CLOCK_SECOND)
|
||||
#define TSCH_EB_PERIOD (16 * CLOCK_SECOND)
|
||||
#endif
|
||||
|
||||
/* Max Period between two consecutive EBs */
|
||||
#ifdef TSCH_CONF_MAX_EB_PERIOD
|
||||
#define TSCH_MAX_EB_PERIOD TSCH_CONF_MAX_EB_PERIOD
|
||||
#else
|
||||
#define TSCH_MAX_EB_PERIOD (50 * CLOCK_SECOND)
|
||||
#endif
|
||||
|
||||
/* Max acceptable join priority */
|
||||
|
@ -157,8 +172,10 @@ extern const struct mac_driver tschmac_driver;
|
|||
|
||||
/* The the TSCH join priority */
|
||||
void tsch_set_join_priority(uint8_t jp);
|
||||
/* The the period at which EBs are sent */
|
||||
/* The period at which EBs are sent */
|
||||
void tsch_set_eb_period(uint32_t period);
|
||||
/* The keep-alive timeout */
|
||||
void tsch_set_ka_timeout(uint32_t timeout);
|
||||
/* Set the node as PAN coordinator */
|
||||
void tsch_set_coordinator(int enable);
|
||||
/* Set the pan as secured or not */
|
||||
|
|
|
@ -184,6 +184,12 @@ packetbuf_totlen(void)
|
|||
return packetbuf_hdrlen() + packetbuf_datalen();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
packetbuf_remaininglen(void)
|
||||
{
|
||||
return PACKETBUF_SIZE - packetbuf_totlen();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
packetbuf_attr_clear(void)
|
||||
{
|
||||
|
|
|
@ -123,6 +123,13 @@ uint16_t packetbuf_datalen(void);
|
|||
*/
|
||||
uint16_t packetbuf_totlen(void);
|
||||
|
||||
/**
|
||||
* \brief Get the total length of the remaining space in the packetbuf
|
||||
* \return Length of the remaining space in the packetbuf
|
||||
*
|
||||
*/
|
||||
uint16_t packetbuf_remaininglen(void);
|
||||
|
||||
/**
|
||||
* \brief Set the length of the data in the packetbuf
|
||||
* \param len The length of the data
|
||||
|
|
|
@ -215,13 +215,13 @@ rpl_parent_is_reachable(rpl_parent_t *p) {
|
|||
if(p == NULL || p->dag == NULL || p->dag->instance == NULL || p->dag->instance->of == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
#ifndef UIP_CONF_ND6_SEND_NA
|
||||
#if UIP_ND6_SEND_NS
|
||||
uip_ds6_nbr_t *nbr = rpl_get_nbr(p);
|
||||
/* Exclude links to a neighbor that is not reachable at a NUD level */
|
||||
if(nbr == NULL || nbr->state != NBR_REACHABLE) {
|
||||
return 0;
|
||||
}
|
||||
#endif /* UIP_CONF_ND6_SEND_NA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
/* If we don't have fresh link information, assume the parent is reachable. */
|
||||
return !rpl_parent_is_fresh(p) || p->dag->instance->of->parent_has_usable_link(p);
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ nullify_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
should_send_dao(rpl_instance_t *instance, rpl_dio_t *dio, rpl_parent_t *p)
|
||||
should_refresh_routes(rpl_instance_t *instance, rpl_dio_t *dio, rpl_parent_t *p)
|
||||
{
|
||||
/* if MOP is set to no downward routes no DAO should be sent */
|
||||
if(instance->mop == RPL_MOP_NO_DOWNWARD_ROUTES) {
|
||||
|
@ -827,12 +827,16 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p)
|
|||
PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n",
|
||||
(unsigned)old_rank, best_dag->rank);
|
||||
RPL_STAT(rpl_stats.parent_switch++);
|
||||
if(RPL_IS_STORING(instance) && last_parent != NULL) {
|
||||
if(RPL_IS_STORING(instance)) {
|
||||
if(last_parent != NULL) {
|
||||
/* Send a No-Path DAO to the removed preferred parent. */
|
||||
dao_output(last_parent, RPL_ZERO_LIFETIME);
|
||||
}
|
||||
/* The DAO parent set changed - schedule a DAO transmission. */
|
||||
/* Trigger DAO transmission from immediate children.
|
||||
* Only for storing mode, see RFC6550 section 9.6. */
|
||||
RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
|
||||
}
|
||||
/* The DAO parent set changed - schedule a DAO transmission. */
|
||||
rpl_schedule_dao(instance);
|
||||
rpl_reset_dio_timer(instance);
|
||||
#if DEBUG
|
||||
|
@ -861,7 +865,10 @@ best_parent(rpl_dag_t *dag, int fresh_only)
|
|||
for(p = nbr_table_head(rpl_parents); p != NULL; p = nbr_table_next(rpl_parents, p)) {
|
||||
|
||||
/* Exclude parents from other DAGs or announcing an infinite rank */
|
||||
if(p->dag != dag || p->rank == INFINITE_RANK) {
|
||||
if(p->dag != dag || p->rank == INFINITE_RANK || p->rank < ROOT_RANK(dag->instance)) {
|
||||
if(p->rank < ROOT_RANK(dag->instance)) {
|
||||
PRINTF("RPL: Parent has invalid rank\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -870,7 +877,7 @@ best_parent(rpl_dag_t *dag, int fresh_only)
|
|||
continue;
|
||||
}
|
||||
|
||||
#ifndef UIP_CONF_ND6_SEND_NA
|
||||
#if UIP_ND6_SEND_NS
|
||||
{
|
||||
uip_ds6_nbr_t *nbr = rpl_get_nbr(p);
|
||||
/* Exclude links to a neighbor that is not reachable at a NUD level */
|
||||
|
@ -878,7 +885,7 @@ best_parent(rpl_dag_t *dag, int fresh_only)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
#endif /* UIP_CONF_ND6_SEND_NA */
|
||||
#endif /* UIP_ND6_SEND_NS */
|
||||
|
||||
/* Now we have an acceptable parent, check if it is the new best */
|
||||
best = of->best_parent(best, p);
|
||||
|
@ -1318,8 +1325,12 @@ rpl_local_repair(rpl_instance_t *instance)
|
|||
instance->has_downward_route = 0;
|
||||
|
||||
rpl_reset_dio_timer(instance);
|
||||
/* Request refresh of DAO registrations next DIO */
|
||||
if(RPL_IS_STORING(instance)) {
|
||||
/* Request refresh of DAO registrations next DIO. Only for storing mode. In
|
||||
* non-storing mode, non-root nodes increment DTSN only on when their parent do,
|
||||
* or on global repair (see RFC6550 section 9.6.) */
|
||||
RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
|
||||
}
|
||||
|
||||
RPL_STAT(rpl_stats.local_repairs++);
|
||||
}
|
||||
|
@ -1534,7 +1545,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
}
|
||||
|
||||
/* The DIO comes from a valid DAG, we can refresh its lifetime */
|
||||
dag->lifetime = (1UL << (instance->dio_intmin + instance->dio_intdoubl)) / 1000;
|
||||
dag->lifetime = (1UL << (instance->dio_intmin + instance->dio_intdoubl)) * RPL_DAG_LIFETIME / 1000;
|
||||
PRINTF("Set dag ");
|
||||
PRINT6ADDR(&dag->dag_id);
|
||||
PRINTF(" lifetime to %ld\n", dag->lifetime);
|
||||
|
@ -1604,7 +1615,9 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
|
||||
/* We don't use route control, so we can have only one official parent. */
|
||||
if(dag->joined && p == dag->preferred_parent) {
|
||||
if(should_send_dao(instance, dio, p)) {
|
||||
if(should_refresh_routes(instance, dio, p)) {
|
||||
/* Our parent is requesting a new DAO. Increment DTSN in turn,
|
||||
* in both storing and non-storing mode (see RFC6550 section 9.6.) */
|
||||
RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
|
||||
rpl_schedule_dao(instance);
|
||||
}
|
||||
|
|
|
@ -201,14 +201,6 @@ rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, nbr_table_reason_t reason, void *
|
|||
}
|
||||
}
|
||||
|
||||
if(nbr != NULL) {
|
||||
#if UIP_ND6_SEND_NA
|
||||
/* set reachable timer if we added or found the nbr entry - and update
|
||||
neighbor entry to reachable to avoid sending NS/NA, etc. */
|
||||
stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
|
||||
nbr->state = NBR_REACHABLE;
|
||||
#endif /* UIP_ND6_SEND_NA */
|
||||
}
|
||||
return nbr;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -145,8 +145,14 @@
|
|||
/* Special value indicating immediate removal. */
|
||||
#define RPL_ZERO_LIFETIME 0
|
||||
|
||||
/* Special value indicating infinite lifetime. */
|
||||
#define RPL_INFINITE_LIFETIME 0xFF
|
||||
|
||||
#define RPL_ROUTE_INFINITE_LIFETIME 0xFFFFFFFF
|
||||
|
||||
#define RPL_LIFETIME(instance, lifetime) \
|
||||
((unsigned long)(instance)->lifetime_unit * (lifetime))
|
||||
(((lifetime) == RPL_INFINITE_LIFETIME) ? RPL_ROUTE_INFINITE_LIFETIME : (unsigned long)(instance)->lifetime_unit * (lifetime))
|
||||
|
||||
|
||||
#ifndef RPL_CONF_MIN_HOPRANKINC
|
||||
/* RFC6550 defines the default MIN_HOPRANKINC as 256.
|
||||
|
|
|
@ -174,7 +174,7 @@ handle_dio_timer(void *ptr)
|
|||
|
||||
if(instance->dio_send) {
|
||||
/* send DIO if counter is less than desired redundancy */
|
||||
if(instance->dio_redundancy != 0 && instance->dio_counter < instance->dio_redundancy) {
|
||||
if(instance->dio_redundancy == 0 || instance->dio_counter < instance->dio_redundancy) {
|
||||
#if RPL_CONF_STATS
|
||||
instance->dio_totsend++;
|
||||
#endif /* RPL_CONF_STATS */
|
||||
|
@ -238,7 +238,7 @@ set_dao_lifetime_timer(rpl_instance_t *instance)
|
|||
|
||||
/* Set up another DAO within half the expiration time, if such a
|
||||
time has been configured */
|
||||
if(instance->lifetime_unit != 0xffff && instance->default_lifetime != 0xff) {
|
||||
if(instance->default_lifetime != RPL_INFINITE_LIFETIME) {
|
||||
clock_time_t expiration_time;
|
||||
expiration_time = (clock_time_t)instance->default_lifetime *
|
||||
(clock_time_t)instance->lifetime_unit *
|
||||
|
|
|
@ -122,7 +122,7 @@ rpl_purge_routes(void)
|
|||
r = uip_ds6_route_head();
|
||||
|
||||
while(r != NULL) {
|
||||
if(r->state.lifetime >= 1) {
|
||||
if(r->state.lifetime >= 1 && r->state.lifetime != RPL_ROUTE_INFINITE_LIFETIME) {
|
||||
/*
|
||||
* If a route is at lifetime == 1, set it to 0, scheduling it for
|
||||
* immediate removal below. This achieves the same as the original code,
|
||||
|
@ -281,11 +281,11 @@ rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr)
|
|||
|
||||
PRINTF("RPL: Neighbor state changed for ");
|
||||
PRINT6ADDR(&nbr->ipaddr);
|
||||
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA
|
||||
#if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA
|
||||
PRINTF(", nscount=%u, state=%u\n", nbr->nscount, nbr->state);
|
||||
#else /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA */
|
||||
#else /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA */
|
||||
PRINTF(", state=%u\n", nbr->state);
|
||||
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA */
|
||||
#endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA */
|
||||
for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) {
|
||||
if(instance->used == 1 ) {
|
||||
p = rpl_find_parent_any_dag(instance, &nbr->ipaddr);
|
||||
|
|
|
@ -68,14 +68,13 @@ mt_start(struct mt_thread *thread, void (* function)(void *), void *data)
|
|||
stack with the correct parameters. */
|
||||
mtarch_start(&thread->thread, function, data);
|
||||
|
||||
thread->state = MT_STATE_READY;
|
||||
thread->state = MT_STATE_STARTED;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void
|
||||
mt_exec(struct mt_thread *thread)
|
||||
{
|
||||
if(thread->state == MT_STATE_READY) {
|
||||
thread->state = MT_STATE_RUNNING;
|
||||
if(thread->state == MT_STATE_STARTED) {
|
||||
current = thread;
|
||||
/* Switch context to the thread. The function call will not return
|
||||
until the the thread has yielded, or is preempted. */
|
||||
|
@ -87,21 +86,18 @@ void
|
|||
mt_yield(void)
|
||||
{
|
||||
mtarch_pstop();
|
||||
current->state = MT_STATE_READY;
|
||||
current = NULL;
|
||||
/* This function is called from the running thread, and we call the
|
||||
switch function in order to switch the thread to the main Contiki
|
||||
program instead. For us, the switch function will not return
|
||||
until the next time we are scheduled to run. */
|
||||
mtarch_yield();
|
||||
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void
|
||||
mt_exit(void)
|
||||
{
|
||||
mtarch_pstop();
|
||||
current->state = MT_STATE_EXITED;
|
||||
current = NULL;
|
||||
mtarch_yield();
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
|
|
@ -84,9 +84,8 @@
|
|||
|
||||
#include "contiki.h"
|
||||
|
||||
#define MT_STATE_READY 1
|
||||
#define MT_STATE_RUNNING 2
|
||||
#define MT_STATE_EXITED 5
|
||||
#define MT_STATE_STARTED 1
|
||||
#define MT_STATE_EXITED 2
|
||||
|
||||
/**
|
||||
* An opaque structure that is used for holding the state of a thread.
|
||||
|
@ -183,18 +182,9 @@ void mtarch_pstop(void);
|
|||
|
||||
struct mt_thread {
|
||||
int state;
|
||||
process_event_t *evptr;
|
||||
process_data_t *dataptr;
|
||||
struct mtarch_thread thread;
|
||||
};
|
||||
|
||||
/**
|
||||
* No error.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define MT_OK 1
|
||||
|
||||
/**
|
||||
* Initializes the multithreading library.
|
||||
*
|
||||
|
|
|
@ -40,9 +40,9 @@ high-level configuration macros may be set:
|
|||
- Default: 2
|
||||
- Purpose: Set the maximum number of concurrent TCP connections.
|
||||
|
||||
- ETHERNET
|
||||
- STATIC_DRIVER
|
||||
- Default: N/A
|
||||
- Purpose: Link Ethernet driver statically instead of loading it dynamically
|
||||
- Purpose: Link device driver statically instead of loading it dynamically
|
||||
using the network configuration file.
|
||||
|
||||
- WITH_LOGGING
|
||||
|
|
|
@ -90,15 +90,15 @@ config_read(char *filename)
|
|||
log_message("Def. Router: ", ipaddrtoa(&config.draddr, uip_buf));
|
||||
log_message("DNS Server: ", ipaddrtoa(&config.resolvaddr, uip_buf));
|
||||
|
||||
#ifndef ETHERNET
|
||||
#ifndef STATIC_DRIVER
|
||||
log_message("Eth. Driver: ", config.ethernetcfg.name);
|
||||
#else /* !ETHERNET */
|
||||
#else /* !STATIC_DRIVER */
|
||||
#define _stringize(arg) #arg
|
||||
#define stringize(arg) _stringize(arg)
|
||||
log_message("Eth. Driver: ", stringize(ETHERNET));
|
||||
#undef _stringize
|
||||
#undef stringize
|
||||
#endif /* !ETHERNET */
|
||||
#endif /* !STATIC_DRIVER */
|
||||
log_message("Driver Port: $", utoa(config.ethernetcfg.addr, uip_buf, 16));
|
||||
|
||||
uip_sethostaddr(&config.hostaddr);
|
||||
|
|
|
@ -63,7 +63,7 @@ ethernet_init(struct ethernet_config *config)
|
|||
{
|
||||
static const char signature[4] = {0x65, 0x74, 0x68, 0x01};
|
||||
|
||||
#ifndef ETHERNET
|
||||
#ifndef STATIC_DRIVER
|
||||
|
||||
struct mod_ctrl module_control = {cfs_read};
|
||||
uint8_t byte;
|
||||
|
@ -91,13 +91,13 @@ ethernet_init(struct ethernet_config *config)
|
|||
}
|
||||
}
|
||||
|
||||
#else /* !ETHERNET */
|
||||
#else /* !STATIC_DRIVER */
|
||||
|
||||
extern void ETHERNET;
|
||||
extern void STATIC_DRIVER;
|
||||
|
||||
module = ÐERNET;
|
||||
module = &STATIC_DRIVER;
|
||||
|
||||
#endif /* !ETHERNET */
|
||||
#endif /* !STATIC_DRIVER */
|
||||
|
||||
module->buffer = uip_buf;
|
||||
module->buffer_size = UIP_BUFSIZE;
|
||||
|
@ -126,8 +126,8 @@ ethernet_exit(void)
|
|||
{
|
||||
module->exit();
|
||||
|
||||
#ifndef ETHERNET
|
||||
#ifndef STATIC_DRIVER
|
||||
mod_free(module);
|
||||
#endif /* !ETHERNET */
|
||||
#endif /* !STATIC_DRIVER */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/**
|
||||
* @defgroup cmsis CMSIS (Cortex Microcontroller Software Interface Standard)
|
||||
* @ingroup arm
|
||||
* \defgroup cmsis CMSIS (Cortex Microcontroller Software Interface Standard)
|
||||
* \ingroup arm
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup aducrf101 ADUCRF101
|
||||
* @ingroup arm
|
||||
* \defgroup aducrf101 ADUCRF101
|
||||
* \ingroup arm
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup at91sam7s AT91SAM7S
|
||||
* @ingroup arm
|
||||
* \defgroup at91sam7s AT91SAM7S
|
||||
* \ingroup arm
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup stm32f103 STM32F103
|
||||
* @ingroup arm
|
||||
* \defgroup stm32f103 STM32F103
|
||||
* \ingroup arm
|
||||
*/
|
||||
|
|
734
cpu/arm/common/CMSIS/cmsis_armcc.h
Normal file
734
cpu/arm/common/CMSIS/cmsis_armcc.h
Normal file
|
@ -0,0 +1,734 @@
|
|||
/**************************************************************************//**
|
||||
* @file cmsis_armcc.h
|
||||
* @brief CMSIS Cortex-M Core Function/Instruction Header File
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- 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.
|
||||
- Neither the name of ARM 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __CMSIS_ARMCC_H
|
||||
#define __CMSIS_ARMCC_H
|
||||
|
||||
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
|
||||
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
|
||||
#endif
|
||||
|
||||
/* ########################### Core Function Access ########################### */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/* intrinsic void __enable_irq(); */
|
||||
/* intrinsic void __disable_irq(); */
|
||||
|
||||
/**
|
||||
\brief Get Control Register
|
||||
\details Returns the content of the Control Register.
|
||||
\return Control Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_CONTROL(void)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
return(__regControl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Control Register
|
||||
\details Writes the given value to the Control Register.
|
||||
\param [in] control Control Register value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
__regControl = control;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get IPSR Register
|
||||
\details Returns the content of the IPSR Register.
|
||||
\return IPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_IPSR(void)
|
||||
{
|
||||
register uint32_t __regIPSR __ASM("ipsr");
|
||||
return(__regIPSR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get APSR Register
|
||||
\details Returns the content of the APSR Register.
|
||||
\return APSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_APSR(void)
|
||||
{
|
||||
register uint32_t __regAPSR __ASM("apsr");
|
||||
return(__regAPSR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get xPSR Register
|
||||
\details Returns the content of the xPSR Register.
|
||||
\return xPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_xPSR(void)
|
||||
{
|
||||
register uint32_t __regXPSR __ASM("xpsr");
|
||||
return(__regXPSR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Process Stack Pointer
|
||||
\details Returns the current value of the Process Stack Pointer (PSP).
|
||||
\return PSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PSP(void)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
return(__regProcessStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Process Stack Pointer
|
||||
\details Assigns the given value to the Process Stack Pointer (PSP).
|
||||
\param [in] topOfProcStack Process Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
__regProcessStackPointer = topOfProcStack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Main Stack Pointer
|
||||
\details Returns the current value of the Main Stack Pointer (MSP).
|
||||
\return MSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_MSP(void)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
return(__regMainStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Main Stack Pointer
|
||||
\details Assigns the given value to the Main Stack Pointer (MSP).
|
||||
\param [in] topOfMainStack Main Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
__regMainStackPointer = topOfMainStack;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Priority Mask
|
||||
\details Returns the current state of the priority mask bit from the Priority Mask Register.
|
||||
\return Priority Mask value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
return(__regPriMask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Priority Mask
|
||||
\details Assigns the given value to the Priority Mask Register.
|
||||
\param [in] priMask Priority Mask
|
||||
*/
|
||||
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
__regPriMask = (priMask);
|
||||
}
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
|
||||
|
||||
/**
|
||||
\brief Enable FIQ
|
||||
\details Enables FIQ interrupts by clearing the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __enable_fault_irq __enable_fiq
|
||||
|
||||
|
||||
/**
|
||||
\brief Disable FIQ
|
||||
\details Disables FIQ interrupts by setting the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __disable_fault_irq __disable_fiq
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Base Priority
|
||||
\details Returns the current value of the Base Priority register.
|
||||
\return Base Priority register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
return(__regBasePri);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Base Priority
|
||||
\details Assigns the given value to the Base Priority register.
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
__regBasePri = (basePri & 0xFFU);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Base Priority with condition
|
||||
\details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
|
||||
or the new value increases the BASEPRI priority level.
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri)
|
||||
{
|
||||
register uint32_t __regBasePriMax __ASM("basepri_max");
|
||||
__regBasePriMax = (basePri & 0xFFU);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Fault Mask
|
||||
\details Returns the current value of the Fault Mask register.
|
||||
\return Fault Mask register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
return(__regFaultMask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set Fault Mask
|
||||
\details Assigns the given value to the Fault Mask register.
|
||||
\param [in] faultMask Fault Mask value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
__regFaultMask = (faultMask & (uint32_t)1);
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */
|
||||
|
||||
|
||||
#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U)
|
||||
|
||||
/**
|
||||
\brief Get FPSCR
|
||||
\details Returns the current value of the Floating Point Status/Control register.
|
||||
\return Floating Point Status/Control register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
return(__regfpscr);
|
||||
#else
|
||||
return(0U);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Set FPSCR
|
||||
\details Assigns the given value to the Floating Point Status/Control register.
|
||||
\param [in] fpscr Floating Point Status/Control value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
__regfpscr = (fpscr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */
|
||||
|
||||
|
||||
|
||||
/*@} end of CMSIS_Core_RegAccFunctions */
|
||||
|
||||
|
||||
/* ########################## Core Instruction Access ######################### */
|
||||
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
|
||||
Access to dedicated instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief No Operation
|
||||
\details No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||
*/
|
||||
#define __NOP __nop
|
||||
|
||||
|
||||
/**
|
||||
\brief Wait For Interrupt
|
||||
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFI __wfi
|
||||
|
||||
|
||||
/**
|
||||
\brief Wait For Event
|
||||
\details Wait For Event is a hint instruction that permits the processor to enter
|
||||
a low-power state until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFE __wfe
|
||||
|
||||
|
||||
/**
|
||||
\brief Send Event
|
||||
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
|
||||
*/
|
||||
#define __SEV __sev
|
||||
|
||||
|
||||
/**
|
||||
\brief Instruction Synchronization Barrier
|
||||
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||
so that all instructions following the ISB are fetched from cache or memory,
|
||||
after the instruction has been completed.
|
||||
*/
|
||||
#define __ISB() do {\
|
||||
__schedule_barrier();\
|
||||
__isb(0xF);\
|
||||
__schedule_barrier();\
|
||||
} while (0U)
|
||||
|
||||
/**
|
||||
\brief Data Synchronization Barrier
|
||||
\details Acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
#define __DSB() do {\
|
||||
__schedule_barrier();\
|
||||
__dsb(0xF);\
|
||||
__schedule_barrier();\
|
||||
} while (0U)
|
||||
|
||||
/**
|
||||
\brief Data Memory Barrier
|
||||
\details Ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
#define __DMB() do {\
|
||||
__schedule_barrier();\
|
||||
__dmb(0xF);\
|
||||
__schedule_barrier();\
|
||||
} while (0U)
|
||||
|
||||
/**
|
||||
\brief Reverse byte order (32 bit)
|
||||
\details Reverses the byte order in integer value.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#define __REV __rev
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse byte order (16 bit)
|
||||
\details Reverses the byte order in two unsigned short values.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
rev16 r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
\brief Reverse byte order in signed short value
|
||||
\details Reverses the byte order in a signed short value with sign extension to integer.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
|
||||
{
|
||||
revsh r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief Rotate Right in unsigned value (32 bit)
|
||||
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||
\param [in] value Value to rotate
|
||||
\param [in] value Number of Bits to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
#define __ROR __ror
|
||||
|
||||
|
||||
/**
|
||||
\brief Breakpoint
|
||||
\details Causes the processor to enter Debug state.
|
||||
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||
\param [in] value is ignored by the processor.
|
||||
If required, a debugger can use it to store additional information about the breakpoint.
|
||||
*/
|
||||
#define __BKPT(value) __breakpoint(value)
|
||||
|
||||
|
||||
/**
|
||||
\brief Reverse bit order of value
|
||||
\details Reverses the bit order of the given value.
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
|
||||
#define __RBIT __rbit
|
||||
#else
|
||||
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
|
||||
|
||||
result = value; /* r will be reversed bits of v; first get LSB of v */
|
||||
for (value >>= 1U; value; value >>= 1U)
|
||||
{
|
||||
result <<= 1U;
|
||||
result |= value & 1U;
|
||||
s--;
|
||||
}
|
||||
result <<= s; /* shift when v's highest bits are zero */
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief Count leading zeros
|
||||
\details Counts the number of leading zeros of a data value.
|
||||
\param [in] value Value to count the leading zeros
|
||||
\return number of leading zeros in value
|
||||
*/
|
||||
#define __CLZ __clz
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
|
||||
|
||||
/**
|
||||
\brief LDR Exclusive (8 bit)
|
||||
\details Executes a exclusive LDR instruction for 8 bit value.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
|
||||
#else
|
||||
#define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief LDR Exclusive (16 bit)
|
||||
\details Executes a exclusive LDR instruction for 16 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
|
||||
#else
|
||||
#define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief LDR Exclusive (32 bit)
|
||||
\details Executes a exclusive LDR instruction for 32 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
|
||||
#else
|
||||
#define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief STR Exclusive (8 bit)
|
||||
\details Executes a exclusive STR instruction for 8 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __STREXB(value, ptr) __strex(value, ptr)
|
||||
#else
|
||||
#define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief STR Exclusive (16 bit)
|
||||
\details Executes a exclusive STR instruction for 16 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __STREXH(value, ptr) __strex(value, ptr)
|
||||
#else
|
||||
#define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief STR Exclusive (32 bit)
|
||||
\details Executes a exclusive STR instruction for 32 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||
#define __STREXW(value, ptr) __strex(value, ptr)
|
||||
#else
|
||||
#define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief Remove the exclusive lock
|
||||
\details Removes the exclusive lock which is created by LDREX.
|
||||
*/
|
||||
#define __CLREX __clrex
|
||||
|
||||
|
||||
/**
|
||||
\brief Signed Saturate
|
||||
\details Saturates a signed value.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (1..32)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __SSAT __ssat
|
||||
|
||||
|
||||
/**
|
||||
\brief Unsigned Saturate
|
||||
\details Saturates an unsigned value.
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __USAT __usat
|
||||
|
||||
|
||||
/**
|
||||
\brief Rotate Right with Extend (32 bit)
|
||||
\details Moves each bit of a bitstring right by one bit.
|
||||
The carry input is shifted in at the left end of the bitstring.
|
||||
\param [in] value Value to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
|
||||
{
|
||||
rrx r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (8 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 8 bit value.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (16 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 16 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
|
||||
|
||||
|
||||
/**
|
||||
\brief LDRT Unprivileged (32 bit)
|
||||
\details Executes a Unprivileged LDRT instruction for 32 bit values.
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (8 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 8 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRBT(value, ptr) __strt(value, ptr)
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (16 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 16 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRHT(value, ptr) __strt(value, ptr)
|
||||
|
||||
|
||||
/**
|
||||
\brief STRT Unprivileged (32 bit)
|
||||
\details Executes a Unprivileged STRT instruction for 32 bit values.
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
*/
|
||||
#define __STRT(value, ptr) __strt(value, ptr)
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */
|
||||
|
||||
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
|
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */
|
||||
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||
Access to dedicated SIMD instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */
|
||||
|
||||
#define __SADD8 __sadd8
|
||||
#define __QADD8 __qadd8
|
||||
#define __SHADD8 __shadd8
|
||||
#define __UADD8 __uadd8
|
||||
#define __UQADD8 __uqadd8
|
||||
#define __UHADD8 __uhadd8
|
||||
#define __SSUB8 __ssub8
|
||||
#define __QSUB8 __qsub8
|
||||
#define __SHSUB8 __shsub8
|
||||
#define __USUB8 __usub8
|
||||
#define __UQSUB8 __uqsub8
|
||||
#define __UHSUB8 __uhsub8
|
||||
#define __SADD16 __sadd16
|
||||
#define __QADD16 __qadd16
|
||||
#define __SHADD16 __shadd16
|
||||
#define __UADD16 __uadd16
|
||||
#define __UQADD16 __uqadd16
|
||||
#define __UHADD16 __uhadd16
|
||||
#define __SSUB16 __ssub16
|
||||
#define __QSUB16 __qsub16
|
||||
#define __SHSUB16 __shsub16
|
||||
#define __USUB16 __usub16
|
||||
#define __UQSUB16 __uqsub16
|
||||
#define __UHSUB16 __uhsub16
|
||||
#define __SASX __sasx
|
||||
#define __QASX __qasx
|
||||
#define __SHASX __shasx
|
||||
#define __UASX __uasx
|
||||
#define __UQASX __uqasx
|
||||
#define __UHASX __uhasx
|
||||
#define __SSAX __ssax
|
||||
#define __QSAX __qsax
|
||||
#define __SHSAX __shsax
|
||||
#define __USAX __usax
|
||||
#define __UQSAX __uqsax
|
||||
#define __UHSAX __uhsax
|
||||
#define __USAD8 __usad8
|
||||
#define __USADA8 __usada8
|
||||
#define __SSAT16 __ssat16
|
||||
#define __USAT16 __usat16
|
||||
#define __UXTB16 __uxtb16
|
||||
#define __UXTAB16 __uxtab16
|
||||
#define __SXTB16 __sxtb16
|
||||
#define __SXTAB16 __sxtab16
|
||||
#define __SMUAD __smuad
|
||||
#define __SMUADX __smuadx
|
||||
#define __SMLAD __smlad
|
||||
#define __SMLADX __smladx
|
||||
#define __SMLALD __smlald
|
||||
#define __SMLALDX __smlaldx
|
||||
#define __SMUSD __smusd
|
||||
#define __SMUSDX __smusdx
|
||||
#define __SMLSD __smlsd
|
||||
#define __SMLSDX __smlsdx
|
||||
#define __SMLSLD __smlsld
|
||||
#define __SMLSLDX __smlsldx
|
||||
#define __SEL __sel
|
||||
#define __QADD __qadd
|
||||
#define __QSUB __qsub
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
|
||||
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
|
||||
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
|
||||
|
||||
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
|
||||
((int64_t)(ARG3) << 32U) ) >> 32U))
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x04) */
|
||||
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||
|
||||
|
||||
#endif /* __CMSIS_ARMCC_H */
|
1800
cpu/arm/common/CMSIS/cmsis_armcc_V6.h
Normal file
1800
cpu/arm/common/CMSIS/cmsis_armcc_V6.h
Normal file
File diff suppressed because it is too large
Load diff
1373
cpu/arm/common/CMSIS/cmsis_gcc.h
Normal file
1373
cpu/arm/common/CMSIS/cmsis_gcc.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,50 +1,59 @@
|
|||
/**
|
||||
* @addtogroup CMSIS_Core_FunctionInterface
|
||||
* @ingroup cmsis
|
||||
* \addtogroup CMSIS_Core_FunctionInterface
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup CMSIS_core_register
|
||||
* @ingroup cmsis
|
||||
* \addtogroup CMSIS_core_register
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup CMSIS_glob_defs
|
||||
* @ingroup cmsis
|
||||
* \addtogroup CMSIS_glob_defs
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup CMSIS_MISRA_Exceptions
|
||||
* @ingroup cmsis
|
||||
* \addtogroup CMSIS_MISRA_Exceptions
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup CMSIS_core_definitions
|
||||
* @ingroup cmsis
|
||||
* \addtogroup CMSIS_core_definitions
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup CMSIS_SIMD_intrinsics
|
||||
* @ingroup cmsis
|
||||
* \addtogroup CMSIS_SIMD_intrinsics
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup CMSIS_Core_InstructionInterface
|
||||
* @ingroup cmsis
|
||||
* \addtogroup CMSIS_Core_InstructionInterface
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Cortex_M0 Cortex-M0
|
||||
* @ingroup cmsis
|
||||
* \defgroup Cortex_M0 Cortex-M0
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Cortex_M3 Cortex-M3
|
||||
* @ingroup cmsis
|
||||
* \defgroup Cortex-M0+ Cortex-M0+
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Cortex_M4 Cortex-M4
|
||||
* @ingroup cmsis
|
||||
* \defgroup Cortex_M3 Cortex-M3
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup Cortex_M4 Cortex-M4
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup Cortex_M7 Cortex-M7
|
||||
* \ingroup cmsis
|
||||
*/
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
/**************************************************************************//**
|
||||
* @file core_cm0.h
|
||||
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
|
||||
* @version V3.30
|
||||
* @date 06. May 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -37,16 +34,21 @@
|
|||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CM0_H_GENERIC
|
||||
#define __CORE_CM0_H_GENERIC
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
|
||||
/**
|
||||
\page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
|
||||
CMSIS violates the following MISRA-C:2004 rules:
|
||||
|
||||
\li Required Rule 8.5, object/function definition in header file.<br>
|
||||
|
@ -63,17 +65,18 @@
|
|||
/*******************************************************************************
|
||||
* CMSIS definitions
|
||||
******************************************************************************/
|
||||
/** \ingroup Cortex_M0
|
||||
/**
|
||||
\ingroup Cortex_M0
|
||||
@{
|
||||
*/
|
||||
|
||||
/* CMSIS CM0 definitions */
|
||||
#define __CM0_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */
|
||||
#define __CM0_CMSIS_VERSION_SUB (0x30) /*!< [15:0] CMSIS HAL sub version */
|
||||
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | \
|
||||
#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
|
||||
#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
|
||||
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
|
||||
__CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
|
||||
|
||||
#define __CORTEX_M (0x00) /*!< Cortex-M Core */
|
||||
#define __CORTEX_M (0x00U) /*!< Cortex-M Core */
|
||||
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
|
@ -81,6 +84,11 @@
|
|||
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
|
||||
#define __STATIC_INLINE static __inline
|
||||
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#define __ASM __asm /*!< asm keyword for ARM Compiler */
|
||||
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
|
||||
#define __STATIC_INLINE static __inline
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
#define __ASM __asm /*!< asm keyword for GNU Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for GNU Compiler */
|
||||
|
@ -100,36 +108,44 @@
|
|||
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#elif defined ( __CSMC__ ) /* Cosmic */
|
||||
#elif defined ( __CSMC__ )
|
||||
#define __packed
|
||||
#define __ASM _asm /*!< asm keyword for COSMIC Compiler */
|
||||
#define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */
|
||||
#define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
|
||||
#define __STATIC_INLINE static inline
|
||||
|
||||
#else
|
||||
#error Unknown compiler
|
||||
#endif
|
||||
|
||||
/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all
|
||||
/** __FPU_USED indicates whether an FPU is used or not.
|
||||
This core does not support an FPU at all
|
||||
*/
|
||||
#define __FPU_USED 0
|
||||
#define __FPU_USED 0U
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
#if defined __TARGET_FPU_VFP
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#if defined __ARM_PCS_VFP
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __GNUC__ )
|
||||
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
#if defined __ARMVFP__
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __TMS470__ )
|
||||
#if defined __TI__VFP_SUPPORT____
|
||||
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#if defined __TI_VFP_SUPPORT__
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __TASKING__ )
|
||||
|
@ -137,15 +153,19 @@
|
|||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#elif defined ( __CSMC__ ) /* Cosmic */
|
||||
#if ( __CSMC__ & 0x400) // FPU present for parser
|
||||
#elif defined ( __CSMC__ )
|
||||
#if ( __CSMC__ & 0x400U)
|
||||
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdint.h> /* standard types definitions */
|
||||
#include <core_cmInstr.h> /* Core Instruction Access */
|
||||
#include <core_cmFunc.h> /* Core Function Access */
|
||||
#include "core_cmInstr.h" /* Core Instruction Access */
|
||||
#include "core_cmFunc.h" /* Core Function Access */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CM0_H_GENERIC */
|
||||
|
||||
|
@ -154,20 +174,24 @@
|
|||
#ifndef __CORE_CM0_H_DEPENDANT
|
||||
#define __CORE_CM0_H_DEPENDANT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* check device defines and use defaults */
|
||||
#if defined __CHECK_DEVICE_DEFINES
|
||||
#ifndef __CM0_REV
|
||||
#define __CM0_REV 0x0000
|
||||
#define __CM0_REV 0x0000U
|
||||
#warning "__CM0_REV not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __NVIC_PRIO_BITS
|
||||
#define __NVIC_PRIO_BITS 2
|
||||
#define __NVIC_PRIO_BITS 2U
|
||||
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
|
||||
#endif
|
||||
|
||||
#ifndef __Vendor_SysTickConfig
|
||||
#define __Vendor_SysTickConfig 0
|
||||
#define __Vendor_SysTickConfig 0U
|
||||
#warning "__Vendor_SysTickConfig not defined in device header file; using default!"
|
||||
#endif
|
||||
#endif
|
||||
|
@ -188,6 +212,11 @@
|
|||
#define __O volatile /*!< Defines 'write only' permissions */
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
|
||||
/* following defines should be used for structure members */
|
||||
#define __IM volatile const /*! Defines 'read only' structure member permissions */
|
||||
#define __OM volatile /*! Defines 'write only' structure member permissions */
|
||||
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
|
||||
|
||||
/*@} end of group Cortex_M0 */
|
||||
|
||||
|
||||
|
@ -200,30 +229,26 @@
|
|||
- Core SCB Register
|
||||
- Core SysTick Register
|
||||
******************************************************************************/
|
||||
/** \defgroup CMSIS_core_register Defines and Type Definitions
|
||||
/**
|
||||
\defgroup CMSIS_core_register Defines and Type Definitions
|
||||
\brief Type definitions and defines for Cortex-M processor based devices.
|
||||
*/
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_CORE Status and Control Registers
|
||||
\brief Core Register type definitions.
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Union type to access the Application Program Status Register (APSR).
|
||||
/**
|
||||
\brief Union type to access the Application Program Status Register (APSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#if (__CORTEX_M != 0x04)
|
||||
uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
|
||||
#else
|
||||
uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
|
||||
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
|
||||
uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
|
||||
#endif
|
||||
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
|
||||
uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
|
||||
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
|
||||
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
|
||||
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
|
||||
|
@ -232,8 +257,22 @@ typedef union
|
|||
uint32_t w; /*!< Type used for word access */
|
||||
} APSR_Type;
|
||||
|
||||
/* APSR Register Definitions */
|
||||
#define APSR_N_Pos 31U /*!< APSR: N Position */
|
||||
#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
|
||||
|
||||
/** \brief Union type to access the Interrupt Program Status Register (IPSR).
|
||||
#define APSR_Z_Pos 30U /*!< APSR: Z Position */
|
||||
#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
|
||||
|
||||
#define APSR_C_Pos 29U /*!< APSR: C Position */
|
||||
#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
|
||||
|
||||
#define APSR_V_Pos 28U /*!< APSR: V Position */
|
||||
#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
|
||||
|
||||
|
||||
/**
|
||||
\brief Union type to access the Interrupt Program Status Register (IPSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
|
@ -245,24 +284,22 @@ typedef union
|
|||
uint32_t w; /*!< Type used for word access */
|
||||
} IPSR_Type;
|
||||
|
||||
/* IPSR Register Definitions */
|
||||
#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
|
||||
#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
|
||||
|
||||
/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
|
||||
|
||||
/**
|
||||
\brief Union type to access the Special-Purpose Program Status Registers (xPSR).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
|
||||
#if (__CORTEX_M != 0x04)
|
||||
uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
|
||||
#else
|
||||
uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
|
||||
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
|
||||
uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
|
||||
#endif
|
||||
uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
|
||||
uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
|
||||
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
|
||||
uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
|
||||
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
|
||||
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
|
||||
uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
|
||||
|
@ -271,215 +308,271 @@ typedef union
|
|||
uint32_t w; /*!< Type used for word access */
|
||||
} xPSR_Type;
|
||||
|
||||
/* xPSR Register Definitions */
|
||||
#define xPSR_N_Pos 31U /*!< xPSR: N Position */
|
||||
#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
|
||||
|
||||
/** \brief Union type to access the Control Registers (CONTROL).
|
||||
#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
|
||||
#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
|
||||
|
||||
#define xPSR_C_Pos 29U /*!< xPSR: C Position */
|
||||
#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
|
||||
|
||||
#define xPSR_V_Pos 28U /*!< xPSR: V Position */
|
||||
#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
|
||||
|
||||
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
|
||||
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
|
||||
|
||||
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
|
||||
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
|
||||
|
||||
|
||||
/**
|
||||
\brief Union type to access the Control Registers (CONTROL).
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
|
||||
uint32_t _reserved0:1; /*!< bit: 0 Reserved */
|
||||
uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
|
||||
uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
|
||||
uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
|
||||
uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
|
||||
} b; /*!< Structure used for bit access */
|
||||
uint32_t w; /*!< Type used for word access */
|
||||
} CONTROL_Type;
|
||||
|
||||
/* CONTROL Register Definitions */
|
||||
#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
|
||||
#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
|
||||
|
||||
/*@} end of group CMSIS_CORE */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
|
||||
\brief Type definitions for the NVIC Registers
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
|
||||
/**
|
||||
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[31];
|
||||
__IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[31];
|
||||
__IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[31];
|
||||
__IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[31];
|
||||
uint32_t RESERVED4[64];
|
||||
__IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
|
||||
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
|
||||
uint32_t RESERVED0[31U];
|
||||
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
|
||||
uint32_t RSERVED1[31U];
|
||||
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
|
||||
uint32_t RESERVED2[31U];
|
||||
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
|
||||
uint32_t RESERVED3[31U];
|
||||
uint32_t RESERVED4[64U];
|
||||
__IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
|
||||
} NVIC_Type;
|
||||
|
||||
/*@} end of group CMSIS_NVIC */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_SCB System Control Block (SCB)
|
||||
\brief Type definitions for the System Control Block Registers
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Structure type to access the System Control Block (SCB).
|
||||
/**
|
||||
\brief Structure type to access the System Control Block (SCB).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
|
||||
__IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
|
||||
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
|
||||
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
|
||||
uint32_t RESERVED0;
|
||||
__IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
|
||||
__IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
|
||||
__IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
|
||||
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
|
||||
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
|
||||
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
|
||||
uint32_t RESERVED1;
|
||||
__IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
|
||||
__IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
|
||||
__IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
|
||||
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
|
||||
} SCB_Type;
|
||||
|
||||
/* SCB CPUID Register Definitions */
|
||||
#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */
|
||||
#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
|
||||
#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
|
||||
|
||||
#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */
|
||||
#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
|
||||
#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
|
||||
|
||||
#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */
|
||||
#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
|
||||
#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
|
||||
|
||||
#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */
|
||||
#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
|
||||
#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
|
||||
|
||||
#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */
|
||||
#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */
|
||||
#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
|
||||
#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
|
||||
|
||||
/* SCB Interrupt Control State Register Definitions */
|
||||
#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */
|
||||
#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
|
||||
#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */
|
||||
#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
|
||||
#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */
|
||||
#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
|
||||
#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */
|
||||
#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
|
||||
#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
|
||||
|
||||
#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */
|
||||
#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
|
||||
#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
|
||||
|
||||
#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */
|
||||
#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
|
||||
#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
|
||||
|
||||
#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */
|
||||
#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
|
||||
#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
|
||||
|
||||
#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */
|
||||
#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
|
||||
#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
|
||||
|
||||
#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */
|
||||
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */
|
||||
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
|
||||
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
|
||||
|
||||
/* SCB Application Interrupt and Reset Control Register Definitions */
|
||||
#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
|
||||
#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
|
||||
#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
|
||||
|
||||
#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */
|
||||
#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
|
||||
#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
|
||||
|
||||
#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */
|
||||
#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
|
||||
#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
|
||||
|
||||
#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
|
||||
|
||||
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */
|
||||
#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
|
||||
#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
|
||||
|
||||
/* SCB System Control Register Definitions */
|
||||
#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */
|
||||
#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
|
||||
#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
|
||||
|
||||
#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */
|
||||
#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
|
||||
#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
|
||||
|
||||
#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */
|
||||
#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
|
||||
#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
|
||||
|
||||
/* SCB Configuration Control Register Definitions */
|
||||
#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */
|
||||
#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
|
||||
#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
|
||||
|
||||
#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */
|
||||
#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
|
||||
#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
|
||||
|
||||
/* SCB System Handler Control and State Register Definitions */
|
||||
#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */
|
||||
#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
|
||||
#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
|
||||
|
||||
/*@} end of group CMSIS_SCB */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_SysTick System Tick Timer (SysTick)
|
||||
\brief Type definitions for the System Timer Registers.
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Structure type to access the System Timer (SysTick).
|
||||
/**
|
||||
\brief Structure type to access the System Timer (SysTick).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
|
||||
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
|
||||
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
|
||||
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
|
||||
__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
|
||||
__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
|
||||
__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
|
||||
__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
|
||||
} SysTick_Type;
|
||||
|
||||
/* SysTick Control / Status Register Definitions */
|
||||
#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
|
||||
#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
|
||||
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
|
||||
|
||||
#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
|
||||
#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
|
||||
#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
|
||||
|
||||
#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
|
||||
#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
|
||||
#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
|
||||
|
||||
#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
|
||||
#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
|
||||
#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
|
||||
#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
|
||||
|
||||
/* SysTick Reload Register Definitions */
|
||||
#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
|
||||
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */
|
||||
#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
|
||||
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
|
||||
|
||||
/* SysTick Current Register Definitions */
|
||||
#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
|
||||
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */
|
||||
#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
|
||||
#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
|
||||
|
||||
/* SysTick Calibration Register Definitions */
|
||||
#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
|
||||
#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
|
||||
#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
|
||||
|
||||
#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
|
||||
#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
|
||||
#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
|
||||
|
||||
#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
|
||||
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_CALIB_TENMS_Pos) /*!< SysTick CALIB: TENMS Mask */
|
||||
#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
|
||||
#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
|
||||
|
||||
/*@} end of group CMSIS_SysTick */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
|
||||
\brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR)
|
||||
are only accessible over DAP and not via processor. Therefore
|
||||
they are not covered by the Cortex-M0 header file.
|
||||
\brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
|
||||
Therefore they are not covered by the Cortex-M0 header file.
|
||||
@{
|
||||
*/
|
||||
/*@} end of group CMSIS_CoreDebug */
|
||||
|
||||
|
||||
/** \ingroup CMSIS_core_register
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_core_bitfield Core register bit field macros
|
||||
\brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
\brief Mask and shift a bit field value for use in a register bit range.
|
||||
\param[in] field Name of the register bit field.
|
||||
\param[in] value Value of the bit field.
|
||||
\return Masked and shifted value.
|
||||
*/
|
||||
#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
|
||||
|
||||
/**
|
||||
\brief Mask and shift a register value to extract a bit filed value.
|
||||
\param[in] field Name of the register bit field.
|
||||
\param[in] value Value of register.
|
||||
\return Masked and shifted bit field value.
|
||||
*/
|
||||
#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
|
||||
|
||||
/*@} end of group CMSIS_core_bitfield */
|
||||
|
||||
|
||||
/**
|
||||
\ingroup CMSIS_core_register
|
||||
\defgroup CMSIS_core_base Core Definitions
|
||||
\brief Definitions for base addresses, unions, and structures.
|
||||
@{
|
||||
|
@ -507,13 +600,15 @@ typedef struct
|
|||
- Core SysTick Functions
|
||||
- Core Register Access Functions
|
||||
******************************************************************************/
|
||||
/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
|
||||
/**
|
||||
\defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ########################## NVIC functions #################################### */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
/**
|
||||
\ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_NVICFunctions NVIC Functions
|
||||
\brief Functions that manage interrupts and exceptions via the NVIC.
|
||||
@{
|
||||
|
@ -521,128 +616,142 @@ typedef struct
|
|||
|
||||
/* Interrupt Priorities are WORD accessible only under ARMv6M */
|
||||
/* The following MACROS handle generation of the register offset and byte masks */
|
||||
#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
|
||||
#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) )
|
||||
#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
|
||||
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
|
||||
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
|
||||
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
|
||||
|
||||
|
||||
/** \brief Enable External Interrupt
|
||||
/**
|
||||
\brief Get External Interrupt Enable State
|
||||
\details Returns whether a device-specific interrupt is enabled in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
\return 0 Interrupt is disabled.
|
||||
\return 1 Interrupt is enabled.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t NVIC_IsIRQEnabled(IRQn_Type IRQn)
|
||||
{
|
||||
return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
|
||||
}
|
||||
|
||||
The function enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
|
||||
/**
|
||||
\brief Enable External Interrupt
|
||||
\details Enables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
|
||||
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Disable External Interrupt
|
||||
|
||||
The function disables a device-specific interrupt in the NVIC interrupt controller.
|
||||
|
||||
/**
|
||||
\brief Disable External Interrupt
|
||||
\details Disables a device-specific interrupt in the NVIC interrupt controller.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
|
||||
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Pending Interrupt
|
||||
|
||||
The function reads the pending register in the NVIC and returns the pending bit
|
||||
for the specified interrupt.
|
||||
|
||||
/**
|
||||
\brief Get Pending Interrupt
|
||||
\details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
|
||||
\return 0 Interrupt status is not pending.
|
||||
\return 1 Interrupt status is pending.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
|
||||
return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Pending Interrupt
|
||||
|
||||
The function sets the pending bit of an external interrupt.
|
||||
|
||||
/**
|
||||
\brief Set Pending Interrupt
|
||||
\details Sets the pending bit of an external interrupt.
|
||||
\param [in] IRQn Interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
|
||||
NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Clear Pending Interrupt
|
||||
|
||||
The function clears the pending bit of an external interrupt.
|
||||
|
||||
/**
|
||||
\brief Clear Pending Interrupt
|
||||
\details Clears the pending bit of an external interrupt.
|
||||
\param [in] IRQn External interrupt number. Value cannot be negative.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
|
||||
NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Interrupt Priority
|
||||
|
||||
The function sets the priority of an interrupt.
|
||||
|
||||
/**
|
||||
\brief Set Interrupt Priority
|
||||
\details Sets the priority of an interrupt.
|
||||
\note The priority cannot be set for every core interrupt.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
|
||||
{
|
||||
if(IRQn < 0) {
|
||||
SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
|
||||
else {
|
||||
NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
|
||||
if ((int32_t)(IRQn) < 0)
|
||||
{
|
||||
SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
|
||||
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Interrupt Priority
|
||||
|
||||
The function reads the priority of an interrupt. The interrupt
|
||||
number can be positive to specify an external (device specific)
|
||||
interrupt, or negative to specify an internal (core) interrupt.
|
||||
|
||||
|
||||
/**
|
||||
\brief Get Interrupt Priority
|
||||
\details Reads the priority of an interrupt.
|
||||
The interrupt number can be positive to specify an external (device specific) interrupt,
|
||||
or negative to specify an internal (core) interrupt.
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return Interrupt Priority. Value is aligned automatically to the implemented
|
||||
priority bits of the microcontroller.
|
||||
\return Interrupt Priority.
|
||||
Value is aligned automatically to the implemented priority bits of the microcontroller.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
|
||||
{
|
||||
|
||||
if(IRQn < 0) {
|
||||
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
|
||||
else {
|
||||
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
|
||||
if ((int32_t)(IRQn) < 0)
|
||||
{
|
||||
return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \brief System Reset
|
||||
|
||||
The function initiates a system reset request to reset the MCU.
|
||||
/**
|
||||
\brief System Reset
|
||||
\details Initiates a system reset request to reset the MCU.
|
||||
*/
|
||||
__STATIC_INLINE void NVIC_SystemReset(void)
|
||||
{
|
||||
__DSB(); /* Ensure all outstanding memory accesses included
|
||||
buffered write are completed before reset */
|
||||
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
|
||||
SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
|
||||
SCB_AIRCR_SYSRESETREQ_Msk);
|
||||
__DSB(); /* Ensure completion of memory access */
|
||||
while(1); /* wait until reset */
|
||||
|
||||
for(;;) /* wait until reset */
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
/*@} end of CMSIS_Core_NVICFunctions */
|
||||
|
@ -650,40 +759,40 @@ __STATIC_INLINE void NVIC_SystemReset(void)
|
|||
|
||||
|
||||
/* ################################## SysTick function ############################################ */
|
||||
/** \ingroup CMSIS_Core_FunctionInterface
|
||||
/**
|
||||
\ingroup CMSIS_Core_FunctionInterface
|
||||
\defgroup CMSIS_Core_SysTickFunctions SysTick Functions
|
||||
\brief Functions that configure the System.
|
||||
@{
|
||||
*/
|
||||
|
||||
#if (__Vendor_SysTickConfig == 0)
|
||||
#if (__Vendor_SysTickConfig == 0U)
|
||||
|
||||
/** \brief System Tick Configuration
|
||||
|
||||
The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||
/**
|
||||
\brief System Tick Configuration
|
||||
\details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||
Counter is in free running mode to generate periodic interrupts.
|
||||
|
||||
\param [in] ticks Number of ticks between two interrupts.
|
||||
|
||||
\return 0 Function succeeded.
|
||||
\return 1 Function failed.
|
||||
|
||||
\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
|
||||
function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
|
||||
must contain a vendor-specific implementation of this function.
|
||||
|
||||
*/
|
||||
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
|
||||
{
|
||||
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
|
||||
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
|
||||
{
|
||||
return (1UL); /* Reload value impossible */
|
||||
}
|
||||
|
||||
SysTick->LOAD = ticks - 1; /* set reload register */
|
||||
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
|
||||
SysTick->VAL = 0; /* Load the SysTick Counter Value */
|
||||
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
|
||||
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
|
||||
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
|
||||
return (0); /* Function successful */
|
||||
return (0UL); /* Function successful */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -693,10 +802,10 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
|
|||
|
||||
|
||||
|
||||
#endif /* __CORE_CM0_H_DEPENDANT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CM0_H_DEPENDANT */
|
||||
|
||||
#endif /* __CMSIS_GENERIC */
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,697 +0,0 @@
|
|||
/**************************************************************************//**
|
||||
* @file core_cm4_simd.h
|
||||
* @brief CMSIS Cortex-M4 SIMD Header File
|
||||
* @version V3.30
|
||||
* @date 17. February 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- 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.
|
||||
- Neither the name of ARM 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CM4_SIMD_H
|
||||
#define __CORE_CM4_SIMD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Hardware Abstraction Layer
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */
|
||||
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||
Access to dedicated SIMD instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
#define __SADD8 __sadd8
|
||||
#define __QADD8 __qadd8
|
||||
#define __SHADD8 __shadd8
|
||||
#define __UADD8 __uadd8
|
||||
#define __UQADD8 __uqadd8
|
||||
#define __UHADD8 __uhadd8
|
||||
#define __SSUB8 __ssub8
|
||||
#define __QSUB8 __qsub8
|
||||
#define __SHSUB8 __shsub8
|
||||
#define __USUB8 __usub8
|
||||
#define __UQSUB8 __uqsub8
|
||||
#define __UHSUB8 __uhsub8
|
||||
#define __SADD16 __sadd16
|
||||
#define __QADD16 __qadd16
|
||||
#define __SHADD16 __shadd16
|
||||
#define __UADD16 __uadd16
|
||||
#define __UQADD16 __uqadd16
|
||||
#define __UHADD16 __uhadd16
|
||||
#define __SSUB16 __ssub16
|
||||
#define __QSUB16 __qsub16
|
||||
#define __SHSUB16 __shsub16
|
||||
#define __USUB16 __usub16
|
||||
#define __UQSUB16 __uqsub16
|
||||
#define __UHSUB16 __uhsub16
|
||||
#define __SASX __sasx
|
||||
#define __QASX __qasx
|
||||
#define __SHASX __shasx
|
||||
#define __UASX __uasx
|
||||
#define __UQASX __uqasx
|
||||
#define __UHASX __uhasx
|
||||
#define __SSAX __ssax
|
||||
#define __QSAX __qsax
|
||||
#define __SHSAX __shsax
|
||||
#define __USAX __usax
|
||||
#define __UQSAX __uqsax
|
||||
#define __UHSAX __uhsax
|
||||
#define __USAD8 __usad8
|
||||
#define __USADA8 __usada8
|
||||
#define __SSAT16 __ssat16
|
||||
#define __USAT16 __usat16
|
||||
#define __UXTB16 __uxtb16
|
||||
#define __UXTAB16 __uxtab16
|
||||
#define __SXTB16 __sxtb16
|
||||
#define __SXTAB16 __sxtab16
|
||||
#define __SMUAD __smuad
|
||||
#define __SMUADX __smuadx
|
||||
#define __SMLAD __smlad
|
||||
#define __SMLADX __smladx
|
||||
#define __SMLALD __smlald
|
||||
#define __SMLALDX __smlaldx
|
||||
#define __SMUSD __smusd
|
||||
#define __SMUSDX __smusdx
|
||||
#define __SMLSD __smlsd
|
||||
#define __SMLSDX __smlsdx
|
||||
#define __SMLSLD __smlsld
|
||||
#define __SMLSLDX __smlsldx
|
||||
#define __SEL __sel
|
||||
#define __QADD __qadd
|
||||
#define __QSUB __qsub
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
|
||||
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
|
||||
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
|
||||
|
||||
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
|
||||
((int64_t)(ARG3) << 32) ) >> 32))
|
||||
|
||||
|
||||
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __SSAT16(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
#define __USAT16(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
|
||||
{
|
||||
union llreg_u{
|
||||
uint32_t w32[2];
|
||||
uint64_t w64;
|
||||
} llr;
|
||||
llr.w64 = acc;
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
|
||||
#else // Big endian
|
||||
__ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
|
||||
#endif
|
||||
|
||||
return(llr.w64);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define __PKHBT(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
|
||||
__ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
#define __PKHTB(ARG1,ARG2,ARG3) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
|
||||
if (ARG3 == 0) \
|
||||
__ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
|
||||
else \
|
||||
__ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
__ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
|
||||
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
|
||||
/* TI CCS specific functions */
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
|
||||
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
|
||||
/* TASKING carm specific functions */
|
||||
/* not yet supported */
|
||||
|
||||
|
||||
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
|
||||
/* Cosmic specific functions */
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CM4_SIMD_H */
|
2525
cpu/arm/common/CMSIS/core_cm7.h
Normal file
2525
cpu/arm/common/CMSIS/core_cm7.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,13 +1,10 @@
|
|||
/**************************************************************************//**
|
||||
* @file core_cmFunc.h
|
||||
* @brief CMSIS Cortex-M Core Function Access Header File
|
||||
* @version V3.30
|
||||
* @date 17. February 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -35,6 +32,12 @@
|
|||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CMFUNC_H
|
||||
#define __CORE_CMFUNC_H
|
||||
|
||||
|
@ -45,589 +48,36 @@
|
|||
@{
|
||||
*/
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
/*------------------ RealView Compiler -----------------*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
#if (__ARMCC_VERSION < 400677)
|
||||
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
|
||||
#endif
|
||||
/*------------------ ARM Compiler V6 -------------------*/
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#include "cmsis_armcc_V6.h"
|
||||
|
||||
/* intrinsic void __enable_irq(); */
|
||||
/* intrinsic void __disable_irq(); */
|
||||
/*------------------ GNU Compiler ----------------------*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
/** \brief Get Control Register
|
||||
|
||||
This function returns the content of the Control Register.
|
||||
|
||||
\return Control Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_CONTROL(void)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
return(__regControl);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Control Register
|
||||
|
||||
This function writes the given value to the Control Register.
|
||||
|
||||
\param [in] control Control Register value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
register uint32_t __regControl __ASM("control");
|
||||
__regControl = control;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get IPSR Register
|
||||
|
||||
This function returns the content of the IPSR Register.
|
||||
|
||||
\return IPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_IPSR(void)
|
||||
{
|
||||
register uint32_t __regIPSR __ASM("ipsr");
|
||||
return(__regIPSR);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get APSR Register
|
||||
|
||||
This function returns the content of the APSR Register.
|
||||
|
||||
\return APSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_APSR(void)
|
||||
{
|
||||
register uint32_t __regAPSR __ASM("apsr");
|
||||
return(__regAPSR);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get xPSR Register
|
||||
|
||||
This function returns the content of the xPSR Register.
|
||||
|
||||
\return xPSR Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_xPSR(void)
|
||||
{
|
||||
register uint32_t __regXPSR __ASM("xpsr");
|
||||
return(__regXPSR);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Process Stack Pointer
|
||||
|
||||
This function returns the current value of the Process Stack Pointer (PSP).
|
||||
|
||||
\return PSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PSP(void)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
return(__regProcessStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Process Stack Pointer
|
||||
|
||||
This function assigns the given value to the Process Stack Pointer (PSP).
|
||||
|
||||
\param [in] topOfProcStack Process Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||
__regProcessStackPointer = topOfProcStack;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Main Stack Pointer
|
||||
|
||||
This function returns the current value of the Main Stack Pointer (MSP).
|
||||
|
||||
\return MSP Register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_MSP(void)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
return(__regMainStackPointer);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Main Stack Pointer
|
||||
|
||||
This function assigns the given value to the Main Stack Pointer (MSP).
|
||||
|
||||
\param [in] topOfMainStack Main Stack Pointer value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
register uint32_t __regMainStackPointer __ASM("msp");
|
||||
__regMainStackPointer = topOfMainStack;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Priority Mask
|
||||
|
||||
This function returns the current state of the priority mask bit from the Priority Mask Register.
|
||||
|
||||
\return Priority Mask value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
return(__regPriMask);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Priority Mask
|
||||
|
||||
This function assigns the given value to the Priority Mask Register.
|
||||
|
||||
\param [in] priMask Priority Mask
|
||||
*/
|
||||
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
register uint32_t __regPriMask __ASM("primask");
|
||||
__regPriMask = (priMask);
|
||||
}
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03)
|
||||
|
||||
/** \brief Enable FIQ
|
||||
|
||||
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __enable_fault_irq __enable_fiq
|
||||
|
||||
|
||||
/** \brief Disable FIQ
|
||||
|
||||
This function disables FIQ interrupts by setting the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
#define __disable_fault_irq __disable_fiq
|
||||
|
||||
|
||||
/** \brief Get Base Priority
|
||||
|
||||
This function returns the current value of the Base Priority register.
|
||||
|
||||
\return Base Priority register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
return(__regBasePri);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Base Priority
|
||||
|
||||
This function assigns the given value to the Base Priority register.
|
||||
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
|
||||
{
|
||||
register uint32_t __regBasePri __ASM("basepri");
|
||||
__regBasePri = (basePri & 0xff);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Fault Mask
|
||||
|
||||
This function returns the current value of the Fault Mask register.
|
||||
|
||||
\return Fault Mask register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
return(__regFaultMask);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Fault Mask
|
||||
|
||||
This function assigns the given value to the Fault Mask register.
|
||||
|
||||
\param [in] faultMask Fault Mask value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
register uint32_t __regFaultMask __ASM("faultmask");
|
||||
__regFaultMask = (faultMask & (uint32_t)1);
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) */
|
||||
|
||||
|
||||
#if (__CORTEX_M == 0x04)
|
||||
|
||||
/** \brief Get FPSCR
|
||||
|
||||
This function returns the current value of the Floating Point Status/Control register.
|
||||
|
||||
\return Floating Point Status/Control register value
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
return(__regfpscr);
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set FPSCR
|
||||
|
||||
This function assigns the given value to the Floating Point Status/Control register.
|
||||
|
||||
\param [in] fpscr Floating Point Status/Control value to set
|
||||
*/
|
||||
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
register uint32_t __regfpscr __ASM("fpscr");
|
||||
__regfpscr = (fpscr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M == 0x04) */
|
||||
|
||||
|
||||
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
|
||||
/** \brief Enable IRQ Interrupts
|
||||
|
||||
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsie i" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Disable IRQ Interrupts
|
||||
|
||||
This function disables IRQ interrupts by setting the I-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsid i" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Control Register
|
||||
|
||||
This function returns the content of the Control Register.
|
||||
|
||||
\return Control Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, control" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Control Register
|
||||
|
||||
This function writes the given value to the Control Register.
|
||||
|
||||
\param [in] control Control Register value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
|
||||
{
|
||||
__ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get IPSR Register
|
||||
|
||||
This function returns the content of the IPSR Register.
|
||||
|
||||
\return IPSR Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get APSR Register
|
||||
|
||||
This function returns the content of the APSR Register.
|
||||
|
||||
\return APSR Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get xPSR Register
|
||||
|
||||
This function returns the content of the xPSR Register.
|
||||
|
||||
\return xPSR Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Process Stack Pointer
|
||||
|
||||
This function returns the current value of the Process Stack Pointer (PSP).
|
||||
|
||||
\return PSP Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Process Stack Pointer
|
||||
|
||||
This function assigns the given value to the Process Stack Pointer (PSP).
|
||||
|
||||
\param [in] topOfProcStack Process Stack Pointer value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||
{
|
||||
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Main Stack Pointer
|
||||
|
||||
This function returns the current value of the Main Stack Pointer (MSP).
|
||||
|
||||
\return MSP Register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Main Stack Pointer
|
||||
|
||||
This function assigns the given value to the Main Stack Pointer (MSP).
|
||||
|
||||
\param [in] topOfMainStack Main Stack Pointer value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||
{
|
||||
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Priority Mask
|
||||
|
||||
This function returns the current state of the priority mask bit from the Priority Mask Register.
|
||||
|
||||
\return Priority Mask value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, primask" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Priority Mask
|
||||
|
||||
This function assigns the given value to the Priority Mask Register.
|
||||
|
||||
\param [in] priMask Priority Mask
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
|
||||
{
|
||||
__ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
|
||||
}
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03)
|
||||
|
||||
/** \brief Enable FIQ
|
||||
|
||||
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsie f" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Disable FIQ
|
||||
|
||||
This function disables FIQ interrupts by setting the F-bit in the CPSR.
|
||||
Can only be executed in Privileged modes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
|
||||
{
|
||||
__ASM volatile ("cpsid f" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Base Priority
|
||||
|
||||
This function returns the current value of the Base Priority register.
|
||||
|
||||
\return Base Priority register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Base Priority
|
||||
|
||||
This function assigns the given value to the Base Priority register.
|
||||
|
||||
\param [in] basePri Base Priority value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
|
||||
{
|
||||
__ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Get Fault Mask
|
||||
|
||||
This function returns the current value of the Fault Mask register.
|
||||
|
||||
\return Fault Mask register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set Fault Mask
|
||||
|
||||
This function assigns the given value to the Fault Mask register.
|
||||
|
||||
\param [in] faultMask Fault Mask value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
|
||||
{
|
||||
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) */
|
||||
|
||||
|
||||
#if (__CORTEX_M == 0x04)
|
||||
|
||||
/** \brief Get FPSCR
|
||||
|
||||
This function returns the current value of the Floating Point Status/Control register.
|
||||
|
||||
\return Floating Point Status/Control register value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
uint32_t result;
|
||||
|
||||
/* Empty asm statement works as a scheduling barrier */
|
||||
__ASM volatile ("");
|
||||
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
|
||||
__ASM volatile ("");
|
||||
return(result);
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Set FPSCR
|
||||
|
||||
This function assigns the given value to the Floating Point Status/Control register.
|
||||
|
||||
\param [in] fpscr Floating Point Status/Control value to set
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||
{
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
/* Empty asm statement works as a scheduling barrier */
|
||||
__ASM volatile ("");
|
||||
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
|
||||
__ASM volatile ("");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M == 0x04) */
|
||||
|
||||
|
||||
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
/*------------------ ICC Compiler ----------------------*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
|
||||
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
|
||||
/* TI CCS specific functions */
|
||||
/*------------------ TI CCS Compiler -------------------*/
|
||||
#elif defined ( __TMS470__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
|
||||
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
|
||||
/* TASKING carm specific functions */
|
||||
/*------------------ TASKING Compiler ------------------*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
|
||||
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
|
||||
/* Cosmic specific functions */
|
||||
/*------------------ COSMIC Compiler -------------------*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
/**************************************************************************//**
|
||||
* @file core_cmInstr.h
|
||||
* @brief CMSIS Cortex-M Core Instruction Access Header File
|
||||
* @version V3.30
|
||||
* @date 17. February 2014
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -35,6 +32,12 @@
|
|||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CMINSTR_H
|
||||
#define __CORE_CMINSTR_H
|
||||
|
||||
|
@ -45,639 +48,36 @@
|
|||
@{
|
||||
*/
|
||||
|
||||
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
|
||||
/* ARM armcc specific functions */
|
||||
/*------------------ RealView Compiler -----------------*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
#if (__ARMCC_VERSION < 400677)
|
||||
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
|
||||
#endif
|
||||
/*------------------ ARM Compiler V6 -------------------*/
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#include "cmsis_armcc_V6.h"
|
||||
|
||||
/*------------------ GNU Compiler ----------------------*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
/** \brief No Operation
|
||||
|
||||
No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||
*/
|
||||
#define __NOP __nop
|
||||
|
||||
|
||||
/** \brief Wait For Interrupt
|
||||
|
||||
Wait For Interrupt is a hint instruction that suspends execution
|
||||
until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFI __wfi
|
||||
|
||||
|
||||
/** \brief Wait For Event
|
||||
|
||||
Wait For Event is a hint instruction that permits the processor to enter
|
||||
a low-power state until one of a number of events occurs.
|
||||
*/
|
||||
#define __WFE __wfe
|
||||
|
||||
|
||||
/** \brief Send Event
|
||||
|
||||
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
|
||||
*/
|
||||
#define __SEV __sev
|
||||
|
||||
|
||||
/** \brief Instruction Synchronization Barrier
|
||||
|
||||
Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||
so that all instructions following the ISB are fetched from cache or
|
||||
memory, after the instruction has been completed.
|
||||
*/
|
||||
#define __ISB() __isb(0xF)
|
||||
|
||||
|
||||
/** \brief Data Synchronization Barrier
|
||||
|
||||
This function acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
#define __DSB() __dsb(0xF)
|
||||
|
||||
|
||||
/** \brief Data Memory Barrier
|
||||
|
||||
This function ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
#define __DMB() __dmb(0xF)
|
||||
|
||||
|
||||
/** \brief Reverse byte order (32 bit)
|
||||
|
||||
This function reverses the byte order in integer value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#define __REV __rev
|
||||
|
||||
|
||||
/** \brief Reverse byte order (16 bit)
|
||||
|
||||
This function reverses the byte order in two unsigned short values.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
rev16 r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief Reverse byte order in signed short value
|
||||
|
||||
This function reverses the byte order in a signed short value with sign extension to integer.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#ifndef __NO_EMBEDDED_ASM
|
||||
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
|
||||
{
|
||||
revsh r0, r0
|
||||
bx lr
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief Rotate Right in unsigned value (32 bit)
|
||||
|
||||
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||
|
||||
\param [in] value Value to rotate
|
||||
\param [in] value Number of Bits to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
#define __ROR __ror
|
||||
|
||||
|
||||
/** \brief Breakpoint
|
||||
|
||||
This function causes the processor to enter Debug state.
|
||||
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||
|
||||
\param [in] value is ignored by the processor.
|
||||
If required, a debugger can use it to store additional information about the breakpoint.
|
||||
*/
|
||||
#define __BKPT(value) __breakpoint(value)
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03)
|
||||
|
||||
/** \brief Reverse bit order of value
|
||||
|
||||
This function reverses the bit order of the given value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
#define __RBIT __rbit
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (8 bit)
|
||||
|
||||
This function performs a exclusive LDR command for 8 bit value.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (16 bit)
|
||||
|
||||
This function performs a exclusive LDR command for 16 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (32 bit)
|
||||
|
||||
This function performs a exclusive LDR command for 32 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
|
||||
|
||||
|
||||
/** \brief STR Exclusive (8 bit)
|
||||
|
||||
This function performs a exclusive STR command for 8 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#define __STREXB(value, ptr) __strex(value, ptr)
|
||||
|
||||
|
||||
/** \brief STR Exclusive (16 bit)
|
||||
|
||||
This function performs a exclusive STR command for 16 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#define __STREXH(value, ptr) __strex(value, ptr)
|
||||
|
||||
|
||||
/** \brief STR Exclusive (32 bit)
|
||||
|
||||
This function performs a exclusive STR command for 32 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
#define __STREXW(value, ptr) __strex(value, ptr)
|
||||
|
||||
|
||||
/** \brief Remove the exclusive lock
|
||||
|
||||
This function removes the exclusive lock which is created by LDREX.
|
||||
|
||||
*/
|
||||
#define __CLREX __clrex
|
||||
|
||||
|
||||
/** \brief Signed Saturate
|
||||
|
||||
This function saturates a signed value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (1..32)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __SSAT __ssat
|
||||
|
||||
|
||||
/** \brief Unsigned Saturate
|
||||
|
||||
This function saturates an unsigned value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __USAT __usat
|
||||
|
||||
|
||||
/** \brief Count leading zeros
|
||||
|
||||
This function counts the number of leading zeros of a data value.
|
||||
|
||||
\param [in] value Value to count the leading zeros
|
||||
\return number of leading zeros in value
|
||||
*/
|
||||
#define __CLZ __clz
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) */
|
||||
|
||||
|
||||
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
|
||||
/* GNU gcc specific functions */
|
||||
|
||||
/* Define macros for porting to both thumb1 and thumb2.
|
||||
* For thumb1, use low register (r0-r7), specified by constrant "l"
|
||||
* Otherwise, use general registers, specified by constrant "r" */
|
||||
#if defined (__thumb__) && !defined (__thumb2__)
|
||||
#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
|
||||
#define __CMSIS_GCC_USE_REG(r) "l" (r)
|
||||
#else
|
||||
#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
|
||||
#define __CMSIS_GCC_USE_REG(r) "r" (r)
|
||||
#endif
|
||||
|
||||
/** \brief No Operation
|
||||
|
||||
No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
|
||||
{
|
||||
__ASM volatile ("nop");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Wait For Interrupt
|
||||
|
||||
Wait For Interrupt is a hint instruction that suspends execution
|
||||
until one of a number of events occurs.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
|
||||
{
|
||||
__ASM volatile ("wfi");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Wait For Event
|
||||
|
||||
Wait For Event is a hint instruction that permits the processor to enter
|
||||
a low-power state until one of a number of events occurs.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
|
||||
{
|
||||
__ASM volatile ("wfe");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Send Event
|
||||
|
||||
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
|
||||
{
|
||||
__ASM volatile ("sev");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Instruction Synchronization Barrier
|
||||
|
||||
Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||
so that all instructions following the ISB are fetched from cache or
|
||||
memory, after the instruction has been completed.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
|
||||
{
|
||||
__ASM volatile ("isb");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Data Synchronization Barrier
|
||||
|
||||
This function acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
|
||||
{
|
||||
__ASM volatile ("dsb");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Data Memory Barrier
|
||||
|
||||
This function ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
|
||||
{
|
||||
__ASM volatile ("dmb");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Reverse byte order (32 bit)
|
||||
|
||||
This function reverses the byte order in integer value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
|
||||
{
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
return __builtin_bswap32(value);
|
||||
#else
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
|
||||
return(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Reverse byte order (16 bit)
|
||||
|
||||
This function reverses the byte order in two unsigned short values.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Reverse byte order in signed short value
|
||||
|
||||
This function reverses the byte order in a signed short value with sign extension to integer.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
|
||||
{
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
return (short)__builtin_bswap16(value);
|
||||
#else
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
|
||||
return(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** \brief Rotate Right in unsigned value (32 bit)
|
||||
|
||||
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||
|
||||
\param [in] value Value to rotate
|
||||
\param [in] value Number of Bits to rotate
|
||||
\return Rotated value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
|
||||
{
|
||||
return (op1 >> op2) | (op1 << (32 - op2));
|
||||
}
|
||||
|
||||
|
||||
/** \brief Breakpoint
|
||||
|
||||
This function causes the processor to enter Debug state.
|
||||
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||
|
||||
\param [in] value is ignored by the processor.
|
||||
If required, a debugger can use it to store additional information about the breakpoint.
|
||||
*/
|
||||
#define __BKPT(value) __ASM volatile ("bkpt "#value)
|
||||
|
||||
|
||||
#if (__CORTEX_M >= 0x03)
|
||||
|
||||
/** \brief Reverse bit order of value
|
||||
|
||||
This function reverses the bit order of the given value.
|
||||
|
||||
\param [in] value Value to reverse
|
||||
\return Reversed value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (8 bit)
|
||||
|
||||
This function performs a exclusive LDR command for 8 bit value.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint8_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
__ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
#else
|
||||
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
|
||||
accepted by assembler. So has to use following less efficient pattern.
|
||||
*/
|
||||
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
|
||||
#endif
|
||||
return ((uint8_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (16 bit)
|
||||
|
||||
This function performs a exclusive LDR command for 16 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint16_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
||||
__ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
#else
|
||||
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
|
||||
accepted by assembler. So has to use following less efficient pattern.
|
||||
*/
|
||||
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
|
||||
#endif
|
||||
return ((uint16_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
|
||||
/** \brief LDR Exclusive (32 bit)
|
||||
|
||||
This function performs a exclusive LDR command for 32 bit values.
|
||||
|
||||
\param [in] ptr Pointer to data
|
||||
\return value of type uint32_t at (*ptr)
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief STR Exclusive (8 bit)
|
||||
|
||||
This function performs a exclusive STR command for 8 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief STR Exclusive (16 bit)
|
||||
|
||||
This function performs a exclusive STR command for 16 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief STR Exclusive (32 bit)
|
||||
|
||||
This function performs a exclusive STR command for 32 bit values.
|
||||
|
||||
\param [in] value Value to store
|
||||
\param [in] ptr Pointer to location
|
||||
\return 0 Function succeeded
|
||||
\return 1 Function failed
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Remove the exclusive lock
|
||||
|
||||
This function removes the exclusive lock which is created by LDREX.
|
||||
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
|
||||
{
|
||||
__ASM volatile ("clrex" ::: "memory");
|
||||
}
|
||||
|
||||
|
||||
/** \brief Signed Saturate
|
||||
|
||||
This function saturates a signed value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (1..32)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __SSAT(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
|
||||
/** \brief Unsigned Saturate
|
||||
|
||||
This function saturates an unsigned value.
|
||||
|
||||
\param [in] value Value to be saturated
|
||||
\param [in] sat Bit position to saturate to (0..31)
|
||||
\return Saturated value
|
||||
*/
|
||||
#define __USAT(ARG1,ARG2) \
|
||||
({ \
|
||||
uint32_t __RES, __ARG1 = (ARG1); \
|
||||
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
|
||||
__RES; \
|
||||
})
|
||||
|
||||
|
||||
/** \brief Count leading zeros
|
||||
|
||||
This function counts the number of leading zeros of a data value.
|
||||
|
||||
\param [in] value Value to count the leading zeros
|
||||
\return number of leading zeros in value
|
||||
*/
|
||||
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
|
||||
return ((uint8_t) result); /* Add explicit type cast here */
|
||||
}
|
||||
|
||||
#endif /* (__CORTEX_M >= 0x03) */
|
||||
|
||||
|
||||
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
|
||||
/* IAR iccarm specific functions */
|
||||
/*------------------ ICC Compiler ----------------------*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
|
||||
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
|
||||
/* TI CCS specific functions */
|
||||
/*------------------ TI CCS Compiler -------------------*/
|
||||
#elif defined ( __TMS470__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
|
||||
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
|
||||
/* TASKING carm specific functions */
|
||||
/*------------------ TASKING Compiler ------------------*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
|
||||
#elif defined ( __CSMC__ ) /*------------------ COSMIC Compiler -------------------*/
|
||||
/* Cosmic specific functions */
|
||||
/*------------------ COSMIC Compiler -------------------*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
|
96
cpu/arm/common/CMSIS/core_cmSimd.h
Normal file
96
cpu/arm/common/CMSIS/core_cmSimd.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/**************************************************************************//**
|
||||
* @file core_cmSimd.h
|
||||
* @brief CMSIS Cortex-M SIMD Header File
|
||||
* @version V4.30
|
||||
* @date 20. October 2015
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- 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.
|
||||
- Neither the name of ARM 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS AND 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.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma system_include /* treat file as system include file for MISRA check */
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#pragma clang system_header /* treat file as system include file */
|
||||
#endif
|
||||
|
||||
#ifndef __CORE_CMSIMD_H
|
||||
#define __CORE_CMSIMD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ################### Compiler specific Intrinsics ########################### */
|
||||
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||
Access to dedicated SIMD instructions
|
||||
@{
|
||||
*/
|
||||
|
||||
/*------------------ RealView Compiler -----------------*/
|
||||
#if defined ( __CC_ARM )
|
||||
#include "cmsis_armcc.h"
|
||||
|
||||
/*------------------ ARM Compiler V6 -------------------*/
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
#include "cmsis_armcc_V6.h"
|
||||
|
||||
/*------------------ GNU Compiler ----------------------*/
|
||||
#elif defined ( __GNUC__ )
|
||||
#include "cmsis_gcc.h"
|
||||
|
||||
/*------------------ ICC Compiler ----------------------*/
|
||||
#elif defined ( __ICCARM__ )
|
||||
#include <cmsis_iar.h>
|
||||
|
||||
/*------------------ TI CCS Compiler -------------------*/
|
||||
#elif defined ( __TMS470__ )
|
||||
#include <cmsis_ccs.h>
|
||||
|
||||
/*------------------ TASKING Compiler ------------------*/
|
||||
#elif defined ( __TASKING__ )
|
||||
/*
|
||||
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||
* Including the CMSIS ones.
|
||||
*/
|
||||
|
||||
/*------------------ COSMIC Compiler -------------------*/
|
||||
#elif defined ( __CSMC__ )
|
||||
#include <cmsis_csm.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CORE_CMSIMD_H */
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
285
cpu/arm/common/sys/mtarch.c
Normal file
285
cpu/arm/common/sys/mtarch.c
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
|
||||
* 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup arm-cm-mtarch
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
* Implmentation of the ARM Cortex-M support for Contiki multi-threading.
|
||||
*/
|
||||
#include CMSIS_DEV_HDR
|
||||
#include "sys/mt.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define EXC_RETURN_PROCESS_THREAD_BASIC_FRAME 0xfffffffd
|
||||
|
||||
/* Check whether EXC_RETURN[3:0] in LR indicates a preempted process thread. */
|
||||
#if __ARM_ARCH == 7
|
||||
#define PREEMPTED_PROCESS_THREAD() \
|
||||
"and r0, lr, #0xf\n\t" \
|
||||
"cmp r0, #0xd\n\t"
|
||||
#elif __ARM_ARCH == 6
|
||||
#define PREEMPTED_PROCESS_THREAD() \
|
||||
"mov r0, lr\n\t" \
|
||||
"movs r1, #0xf\n\t" \
|
||||
"and r0, r1\n\t" \
|
||||
"cmp r0, #0xd\n\t"
|
||||
#else
|
||||
#error Unsupported ARM architecture
|
||||
#endif
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief SVCall system handler
|
||||
*
|
||||
* This exception handler executes the action requested by the corresponding
|
||||
* \c svc instruction, which is a task switch from the main Contiki thread to an
|
||||
* mt thread or the other way around.
|
||||
*/
|
||||
__attribute__ ((__naked__))
|
||||
void
|
||||
svcall_handler(void)
|
||||
{
|
||||
/* This is a controlled system handler, so do not use ENERGEST_TYPE_IRQ. */
|
||||
|
||||
/*
|
||||
* Decide whether to switch to the main thread or to a process thread,
|
||||
* depending on the type of the thread preempted by SVCall.
|
||||
*/
|
||||
__asm__ (PREEMPTED_PROCESS_THREAD()
|
||||
#if __ARM_ARCH == 7
|
||||
"it eq\n\t"
|
||||
#endif
|
||||
"beq switch_to_main_thread\n\t"
|
||||
|
||||
/*
|
||||
* - Retrieve from the main stack the PSP passed to SVCall through R0. Note
|
||||
* that it cannot be retrieved directly from R0 on exception entry because
|
||||
* this register may have been overwritten by other exceptions on SVCall
|
||||
* entry.
|
||||
* - Save the main thread context to the main stack.
|
||||
* - Restore the process thread context from the process stack.
|
||||
* - Return to Thread mode, resuming the process thread.
|
||||
*/
|
||||
#if __ARM_ARCH == 7
|
||||
"ldr r0, [sp]\n\t"
|
||||
"push {r4-r11, lr}\n\t"
|
||||
"add r1, r0, #9 * 4\n\t"
|
||||
"msr psp, r1\n\t"
|
||||
"ldmia r0, {r4-r11, pc}");
|
||||
#elif __ARM_ARCH == 6
|
||||
"mov r0, r8\n\t"
|
||||
"mov r1, r9\n\t"
|
||||
"mov r2, r10\n\t"
|
||||
"mov r3, r11\n\t"
|
||||
"push {r0-r7, lr}\n\t"
|
||||
"ldr r0, [sp, #9 * 4]\n\t"
|
||||
"ldmia r0!, {r4-r7}\n\t"
|
||||
"mov r8, r4\n\t"
|
||||
"mov r9, r5\n\t"
|
||||
"mov r10, r6\n\t"
|
||||
"mov r11, r7\n\t"
|
||||
"ldmia r0!, {r3-r7}\n\t"
|
||||
"msr psp, r0\n\t"
|
||||
"bx r3");
|
||||
#endif
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief PendSV system handler
|
||||
*
|
||||
* This exception handler executes following a call to mtarch_pstart() from
|
||||
* another exception handler. It performs a task switch to the main Contiki
|
||||
* thread if it is not already running.
|
||||
*/
|
||||
__attribute__ ((__naked__))
|
||||
void
|
||||
pendsv_handler(void)
|
||||
{
|
||||
/* This is a controlled system handler, so do not use ENERGEST_TYPE_IRQ. */
|
||||
|
||||
/*
|
||||
* Return without doing anything if PendSV has not preempted a process thread.
|
||||
* This can occur either because PendSV has preempted the main thread, in
|
||||
* which case there is nothing to do, or because mtarch_pstart() has been
|
||||
* called from an exception handler without having called mt_init() first, in
|
||||
* which case PendSV may have preempted an exception handler and nothing must
|
||||
* be done because mt is not active.
|
||||
*/
|
||||
__asm__ ( PREEMPTED_PROCESS_THREAD()
|
||||
#if __ARM_ARCH == 7
|
||||
"it ne\n\t"
|
||||
"bxne lr\n"
|
||||
#elif __ARM_ARCH == 6
|
||||
"beq switch_to_main_thread\n\t"
|
||||
"bx lr\n"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* - Save the process thread context to the process stack.
|
||||
* - Place into the main stack the updated PSP that SVCall must return through
|
||||
* R0.
|
||||
* - Restore the main thread context from the main stack.
|
||||
* - Return to Thread mode, resuming the main thread.
|
||||
*/
|
||||
"switch_to_main_thread:\n\t"
|
||||
"mrs r0, psp\n\t"
|
||||
#if __ARM_ARCH == 7
|
||||
"stmdb r0!, {r4-r11, lr}\n\t"
|
||||
"str r0, [sp, #9 * 4]\n\t"
|
||||
"pop {r4-r11, pc}");
|
||||
#elif __ARM_ARCH == 6
|
||||
"mov r3, lr\n\t"
|
||||
"sub r0, #5 * 4\n\t"
|
||||
"stmia r0!, {r3-r7}\n\t"
|
||||
"mov r4, r8\n\t"
|
||||
"mov r5, r9\n\t"
|
||||
"sub r0, #9 * 4\n\t"
|
||||
"mov r6, r10\n\t"
|
||||
"mov r7, r11\n\t"
|
||||
"stmia r0!, {r4-r7}\n\t"
|
||||
"pop {r4-r7}\n\t"
|
||||
"sub r0, #4 * 4\n\t"
|
||||
"mov r8, r4\n\t"
|
||||
"mov r9, r5\n\t"
|
||||
"str r0, [sp, #5 * 4]\n\t"
|
||||
"mov r10, r6\n\t"
|
||||
"mov r11, r7\n\t"
|
||||
"pop {r4-r7, pc}");
|
||||
#endif
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtarch_init(void)
|
||||
{
|
||||
SCB->CCR = (SCB->CCR
|
||||
#ifdef SCB_CCR_NONBASETHRDENA_Msk
|
||||
/*
|
||||
* Make sure that any attempt to enter Thread mode with exceptions
|
||||
* active faults.
|
||||
*
|
||||
* Only SVCall and PendSV are allowed to forcibly enter Thread
|
||||
* mode, and they are configured with the same, lowest exception
|
||||
* priority, so no other exceptions may be active.
|
||||
*/
|
||||
& ~SCB_CCR_NONBASETHRDENA_Msk
|
||||
#endif
|
||||
/*
|
||||
* Force 8-byte stack pointer alignment on exception entry in order
|
||||
* to be able to use AAPCS-conforming functions as exception
|
||||
* handlers.
|
||||
*/
|
||||
) | SCB_CCR_STKALIGN_Msk;
|
||||
|
||||
/*
|
||||
* Configure SVCall and PendSV with the same, lowest exception priority.
|
||||
*
|
||||
* This makes sure that they cannot preempt each other, and that the processor
|
||||
* executes them after having handled all other exceptions. If both are
|
||||
* pending at the same time, then SVCall takes precedence because of its lower
|
||||
* exception number. In addition, the associated exception handlers do not
|
||||
* have to check whether they are returning to Thread mode, because they
|
||||
* cannot preempt any other exception.
|
||||
*/
|
||||
NVIC_SetPriority(SVCall_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
|
||||
/*
|
||||
* Force the preceding configurations to take effect before further
|
||||
* operations.
|
||||
*/
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtarch_start(struct mtarch_thread *thread,
|
||||
void (*function)(void *data), void *data)
|
||||
{
|
||||
struct mtarch_thread_context *context = &thread->start_stack.context;
|
||||
|
||||
/*
|
||||
* Initialize the thread context with the appropriate values to call
|
||||
* function() with data and to make function() return to mt_exit() without
|
||||
* having to call it explicitly.
|
||||
*/
|
||||
context->exc_return = EXC_RETURN_PROCESS_THREAD_BASIC_FRAME;
|
||||
context->r0 = (uint32_t)data;
|
||||
context->lr = (uint32_t)mt_exit;
|
||||
context->pc = (uint32_t)function;
|
||||
context->xpsr = xPSR_T_Msk;
|
||||
thread->psp = (uint32_t)context;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtarch_exec(struct mtarch_thread *thread)
|
||||
{
|
||||
/* Pass the PSP to SVCall, and get the updated PSP as its return value. */
|
||||
register uint32_t psp __asm__ ("r0") = thread->psp;
|
||||
__asm__ volatile ("svc #0"
|
||||
: "+r" (psp)
|
||||
:: "memory");
|
||||
thread->psp = psp;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
__attribute__ ((__naked__))
|
||||
void
|
||||
mtarch_yield(void)
|
||||
{
|
||||
/* Invoke SVCall. */
|
||||
__asm__ ("svc #0\n\t"
|
||||
"bx lr");
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtarch_stop(struct mtarch_thread *thread)
|
||||
{
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtarch_pstart(void)
|
||||
{
|
||||
/* Trigger PendSV. */
|
||||
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtarch_pstop(void)
|
||||
{
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
mtarch_remove(void)
|
||||
{
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/** @} */
|
119
cpu/arm/common/sys/mtarch.h
Normal file
119
cpu/arm/common/sys/mtarch.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
|
||||
* 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup arm
|
||||
* @{
|
||||
*
|
||||
* \defgroup arm-cm-mtarch ARM Cortex-M support for Contiki multi-threading
|
||||
*
|
||||
* All the Cortex-M devices supported by CMSIS-CORE are supported.
|
||||
*
|
||||
* An exception handler can decide to make the main Contiki thread preempt any
|
||||
* running mt thread by calling mtarch_pstart() (e.g. to perform urgent
|
||||
* operations that have been triggered by some event or that had been
|
||||
* scheduled). If the running thread is already the main Contiki thread, then
|
||||
* nothing happens. The corresponding task switch takes place when leaving
|
||||
* Handler mode. The main Contiki thread then resumes after the call to
|
||||
* mt_exec() that yielded to the preempted mt thread.
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
* Header file for the ARM Cortex-M support for Contiki multi-threading.
|
||||
*/
|
||||
#ifndef MTARCH_H_
|
||||
#define MTARCH_H_
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "sys/cc.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef MTARCH_CONF_STACKSIZE
|
||||
/** Thread stack size configuration, expressed as a number of 32-bit words. */
|
||||
#define MTARCH_CONF_STACKSIZE 256
|
||||
#endif
|
||||
/** Actual stack size, with minimum size and alignment requirements enforced. */
|
||||
#define MTARCH_STACKSIZE ((MAX(MTARCH_CONF_STACKSIZE, \
|
||||
sizeof(struct mtarch_thread_context) / \
|
||||
sizeof(uint32_t)) + 1) & ~1)
|
||||
|
||||
/**
|
||||
* Structure of a saved thread context.
|
||||
*
|
||||
* <tt>xpsr..r0</tt> are managed by the processor (except in mtarch_start()),
|
||||
* while the other register values are handled by the software.
|
||||
*/
|
||||
struct mtarch_thread_context {
|
||||
#if __ARM_ARCH == 7
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
#endif
|
||||
uint32_t r8;
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
uint32_t exc_return;
|
||||
#if __ARM_ARCH == 6
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
#endif
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t xpsr;
|
||||
};
|
||||
|
||||
struct mtarch_thread {
|
||||
uint32_t psp;
|
||||
union {
|
||||
struct {
|
||||
uint32_t free[MTARCH_STACKSIZE -
|
||||
sizeof(struct mtarch_thread_context) / sizeof(uint32_t)];
|
||||
struct mtarch_thread_context context;
|
||||
} start_stack;
|
||||
uint32_t stack[MTARCH_STACKSIZE];
|
||||
} CC_ALIGN(8);
|
||||
};
|
||||
|
||||
#endif /* MTARCH_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -14,7 +14,7 @@ LDSCRIPT = $(OBJECTDIR)/cc2538.ld
|
|||
CFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
CFLAGS += -fshort-enums -fomit-frame-pointer -fno-strict-aliasing
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wall -DCMSIS_DEV_HDR=\"cc2538_cm3.h\"
|
||||
LDFLAGS += -mcpu=cortex-m3 -mthumb -nostartfiles
|
||||
LDFLAGS += -T $(LDSCRIPT)
|
||||
LDFLAGS += -Wl,--gc-sections,--sort-section=alignment
|
||||
|
@ -42,7 +42,7 @@ endif
|
|||
CLEAN += symbols.c symbols.h *.d *.elf *.hex
|
||||
|
||||
### CPU-dependent directories
|
||||
CONTIKI_CPU_DIRS = . dev usb
|
||||
CONTIKI_CPU_DIRS = ../arm/common/CMSIS . dev usb
|
||||
|
||||
### Use the existing debug I/O in cpu/arm/common
|
||||
CONTIKI_CPU_DIRS += ../arm/common/dbg-io
|
||||
|
@ -52,7 +52,7 @@ CONTIKI_CPU_DIRS += ../cc253x/usb/common ../cc253x/usb/common/cdc-acm
|
|||
|
||||
### CPU-dependent source files
|
||||
CONTIKI_CPU_SOURCEFILES += soc.c clock.c rtimer-arch.c uart.c watchdog.c
|
||||
CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c
|
||||
CONTIKI_CPU_SOURCEFILES += nvic.c sys-ctrl.c gpio.c ioc.c spi.c adc.c
|
||||
CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ecb.c cbc.c ctr.c cbc-mac.c gcm.c
|
||||
CONTIKI_CPU_SOURCEFILES += ccm.c sha256.c
|
||||
CONTIKI_CPU_SOURCEFILES += cc2538-aes-128.c cc2538-ccm-star.c
|
||||
|
@ -79,7 +79,7 @@ CPU_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CPU_START_SOURCEFILES
|
|||
CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES)
|
||||
CONTIKI_SOURCEFILES += $(USB_CORE_SOURCEFILES) $(USB_ARCH_SOURCEFILES)
|
||||
|
||||
MODULES += lib/newlib
|
||||
MODULES += lib/newlib cpu/arm/common/sys
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
|
@ -123,4 +123,4 @@ LDGENFLAGS += -x c -P -E
|
|||
# NB: Assumes LDSCRIPT was not overridden and is in $(OBJECTDIR)
|
||||
$(LDSCRIPT): $(SOURCE_LDSCRIPT) FORCE | $(OBJECTDIR)
|
||||
$(TRACE_CC)
|
||||
$(Q)$(CC) $(LDGENFLAGS) $< -o $@
|
||||
$(Q)$(CC) $(LDGENFLAGS) $< | grep -v '^\s*#\s*pragma\>' > $@
|
||||
|
|
144
cpu/cc2538/cc2538_cm3.h
Normal file
144
cpu/cc2538/cc2538_cm3.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Template:
|
||||
* Copyright (c) 2012 ARM LIMITED
|
||||
* All rights reserved.
|
||||
*
|
||||
* CC2538:
|
||||
* Copyright (c) 2016, Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
|
||||
* 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup cc2538
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc2538-cm3 CC2538 Cortex-M3
|
||||
*
|
||||
* CC2538 Cortex-M3 CMSIS definitions
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
* CMSIS Cortex-M3 core peripheral access layer header file for CC2538
|
||||
*/
|
||||
#ifndef CC2538_CM3_H
|
||||
#define CC2538_CM3_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup CC2538_CMSIS CC2538 CMSIS Definitions
|
||||
* Configuration of the Cortex-M3 Processor and Core Peripherals
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \name Interrupt Number Definition
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum IRQn
|
||||
{
|
||||
/****** Cortex-M3 Processor Exceptions Numbers ****************************/
|
||||
NonMaskableInt_IRQn = -14, /**< 2 Non Maskable Interrupt */
|
||||
HardFault_IRQn = -13, /**< 3 HardFault Interrupt */
|
||||
MemoryManagement_IRQn = -12, /**< 4 Memory Management Interrupt */
|
||||
BusFault_IRQn = -11, /**< 5 Bus Fault Interrupt */
|
||||
UsageFault_IRQn = -10, /**< 6 Usage Fault Interrupt */
|
||||
SVCall_IRQn = -5, /**< 11 SV Call Interrupt */
|
||||
DebugMonitor_IRQn = -4, /**< 12 Debug Monitor Interrupt */
|
||||
PendSV_IRQn = -2, /**< 14 Pend SV Interrupt */
|
||||
SysTick_IRQn = -1, /**< 15 System Tick Interrupt */
|
||||
|
||||
/****** CC2538-Specific Interrupt Numbers *********************************/
|
||||
GPIO_A_IRQn = 0, /**< GPIO port A Interrupt */
|
||||
GPIO_B_IRQn = 1, /**< GPIO port B Interrupt */
|
||||
GPIO_C_IRQn = 2, /**< GPIO port C Interrupt */
|
||||
GPIO_D_IRQn = 3, /**< GPIO port D Interrupt */
|
||||
UART0_IRQn = 5, /**< UART0 Interrupt */
|
||||
UART1_IRQn = 6, /**< UART1 Interrupt */
|
||||
SSI0_IRQn = 7, /**< SSI0 Interrupt */
|
||||
I2C_IRQn = 8, /**< I²C Interrupt */
|
||||
ADC_IRQn = 14, /**< ADC Interrupt */
|
||||
WDT_IRQn = 18, /**< Watchdog Timer Interrupt */
|
||||
GPT0A_IRQn = 19, /**< GPTimer 0A Interrupt */
|
||||
GPT0B_IRQn = 20, /**< GPTimer 0B Interrupt */
|
||||
GPT1A_IRQn = 21, /**< GPTimer 1A Interrupt */
|
||||
GPT1B_IRQn = 22, /**< GPTimer 1B Interrupt */
|
||||
GPT2A_IRQn = 23, /**< GPTimer 2A Interrupt */
|
||||
GPT2B_IRQn = 24, /**< GPTimer 2B Interrupt */
|
||||
ADC_CMP_IRQn = 25, /**< Analog Comparator Interrupt */
|
||||
RF_TX_RX_ALT_IRQn = 26, /**< RF Tx/Rx (Alternate) Interrupt */
|
||||
RF_ERR_ALT_IRQn = 27, /**< RF Error (Alternate) Interrupt */
|
||||
SYS_CTRL_IRQn = 28, /**< System Control Interrupt */
|
||||
FLASH_CTRL_IRQn = 29, /**< Flash memory Control Interrupt */
|
||||
AES_ALT_IRQn = 30, /**< AES (Alternate) Interrupt */
|
||||
PKA_ALT_IRQn = 31, /**< PKA (Alternate) Interrupt */
|
||||
SMT_ALT_IRQn = 32, /**< SM Timer (Alternate) Interrupt */
|
||||
MACT_ALT_IRQn = 33, /**< MAC Timer (Alternate) Interrupt */
|
||||
SSI1_IRQn = 34, /**< SSI1 Interrupt */
|
||||
GPT3A_IRQn = 35, /**< GPTimer 3A Interrupt */
|
||||
GPT3B_IRQn = 36, /**< GPTimer 3B Interrupt */
|
||||
UDMA_SW_IRQn = 46, /**< µDMA Software Interrupt */
|
||||
UDMA_ERR_IRQn = 47, /**< µDMA Error Interrupt */
|
||||
USB_IRQn = 140, /**< USB Interrupt */
|
||||
RF_TX_RX_IRQn = 141, /**< RF Tx/Rx Interrupt */
|
||||
RF_ERR_IRQn = 142, /**< RF Error Interrupt */
|
||||
AES_IRQn = 143, /**< AES Interrupt */
|
||||
PKA_IRQn = 144, /**< PKA Interrupt */
|
||||
SMT_IRQn = 145, /**< SM Timer Interrupt */
|
||||
MACT_IRQn = 146 /**< MAC Timer Interrupt */
|
||||
} IRQn_Type;
|
||||
|
||||
/** @} */
|
||||
|
||||
/** \name Processor and Core Peripheral Section
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Configuration of the Cortex-M3 Processor and Core Peripherals */
|
||||
#define __CM3_REV 0x0200 /**< Core Revision r2p0 */
|
||||
#define __MPU_PRESENT 1 /**< MPU present or not */
|
||||
#define __NVIC_PRIO_BITS 3 /**< Number of Bits used for Priority Levels */
|
||||
#define __Vendor_SysTickConfig 0 /**< Set to 1 if different SysTick Config is used */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */ /* CC2538_CMSIS */
|
||||
|
||||
#include <core_cm3.h> /* Cortex-M3 processor and core peripherals */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CC2538_CM3_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -49,7 +49,7 @@
|
|||
* Clock driver implementation for the TI cc2538
|
||||
*/
|
||||
#include "contiki.h"
|
||||
#include "systick.h"
|
||||
#include "cc2538_cm3.h"
|
||||
#include "reg.h"
|
||||
#include "cpu.h"
|
||||
#include "dev/gptimer.h"
|
||||
|
@ -69,12 +69,12 @@
|
|||
#endif
|
||||
#define PRESCALER_VALUE (SYS_CTRL_SYS_CLOCK / SYS_CTRL_1MHZ - 1)
|
||||
|
||||
/* Reload value for SysTick counter */
|
||||
/* Period of the SysTick counter expressed as a number of ticks */
|
||||
#if SYS_CTRL_SYS_CLOCK % CLOCK_SECOND
|
||||
/* Too low clock speeds will lead to reduced accurracy */
|
||||
#error System clock speed too slow for CLOCK_SECOND, accuracy reduced
|
||||
#endif
|
||||
#define RELOAD_VALUE (SYS_CTRL_SYS_CLOCK / CLOCK_SECOND - 1)
|
||||
#define SYSTICK_PERIOD (SYS_CTRL_SYS_CLOCK / CLOCK_SECOND)
|
||||
|
||||
static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -92,13 +92,7 @@ static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0;
|
|||
void
|
||||
clock_init(void)
|
||||
{
|
||||
REG(SYSTICK_STRELOAD) = RELOAD_VALUE;
|
||||
|
||||
/* System clock source, Enable */
|
||||
REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_CLK_SRC | SYSTICK_STCTRL_ENABLE;
|
||||
|
||||
/* Enable the SysTick Interrupt */
|
||||
REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_INTEN;
|
||||
SysTick_Config(SYSTICK_PERIOD);
|
||||
|
||||
/*
|
||||
* Remove the clock gate to enable GPT0 and then initialise it
|
||||
|
@ -230,12 +224,12 @@ void
|
|||
clock_adjust(void)
|
||||
{
|
||||
/* Halt the SysTick while adjusting */
|
||||
REG(SYSTICK_STCTRL) &= ~SYSTICK_STCTRL_ENABLE;
|
||||
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
|
||||
|
||||
update_ticks();
|
||||
|
||||
/* Re-Start the SysTick */
|
||||
REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_ENABLE;
|
||||
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
|
|
@ -54,17 +54,13 @@
|
|||
#ifndef CPU_H_
|
||||
#define CPU_H_
|
||||
|
||||
/** \brief Disables all CPU interrupts */
|
||||
unsigned long cpu_cpsid(void);
|
||||
#include "cc2538_cm3.h"
|
||||
|
||||
/** \brief Enables all CPU interrupts */
|
||||
unsigned long cpu_cpsie(void);
|
||||
|
||||
/** \brief Enables all CPU interrupts */
|
||||
#define INTERRUPTS_ENABLE() cpu_cpsie()
|
||||
#define INTERRUPTS_ENABLE() __enable_irq()
|
||||
|
||||
/** \brief Disables all CPU interrupts. */
|
||||
#define INTERRUPTS_DISABLE() cpu_cpsid()
|
||||
#define INTERRUPTS_DISABLE() __disable_irq()
|
||||
|
||||
#endif /* CPU_H_ */
|
||||
|
||||
|
|
|
@ -237,8 +237,8 @@ aes_auth_crypt_start(uint32_t ctrl, uint8_t key_area, const void *iv,
|
|||
|
||||
if(process != NULL) {
|
||||
crypto_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_AES);
|
||||
nvic_interrupt_enable(NVIC_INT_AES);
|
||||
NVIC_ClearPendingIRQ(AES_IRQn);
|
||||
NVIC_EnableIRQ(AES_IRQn);
|
||||
}
|
||||
|
||||
if(data_len != 0) {
|
||||
|
@ -282,7 +282,7 @@ aes_auth_crypt_get_result(void *iv, void *tag)
|
|||
AES_CTRL_INT_CLR_KEY_ST_WR_ERR |
|
||||
AES_CTRL_INT_CLR_KEY_ST_RD_ERR;
|
||||
|
||||
nvic_interrupt_disable(NVIC_INT_AES);
|
||||
NVIC_DisableIRQ(AES_IRQn);
|
||||
crypto_register_process_notification(NULL);
|
||||
|
||||
/* Disable the master control / DMA clock */
|
||||
|
|
|
@ -130,8 +130,8 @@ bignum_mod_start(const uint32_t *number,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -158,7 +158,7 @@ bignum_mod_get_result(uint32_t *buffer,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Get the MSW register value. */
|
||||
|
@ -238,8 +238,8 @@ bignum_cmp_start(const uint32_t *number1,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -257,7 +257,7 @@ bignum_cmp_get_result(void)
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Check the compare register. */
|
||||
|
@ -346,8 +346,8 @@ bignum_inv_mod_start(const uint32_t *number,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -374,7 +374,7 @@ bignum_inv_mod_get_result(uint32_t *buffer,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Get the MSW register value. */
|
||||
|
@ -469,8 +469,8 @@ bignum_mul_start(const uint32_t *multiplicand,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -498,7 +498,7 @@ bignum_mul_get_result(uint32_t *buffer,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Get the MSW register value. */
|
||||
|
@ -594,8 +594,8 @@ bignum_add_start(const uint32_t *number1,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -623,7 +623,7 @@ bignum_add_get_result(uint32_t *buffer,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Get the MSW register value. */
|
||||
|
@ -720,8 +720,8 @@ bignum_subtract_start(const uint32_t *number1,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -749,7 +749,7 @@ bignum_subtract_get_result(uint32_t *buffer,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Get the MSW register value. */
|
||||
|
@ -864,8 +864,8 @@ bignum_exp_mod_start(const uint32_t *number,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -892,7 +892,7 @@ bignum_exp_mod_get_result(uint32_t *buffer,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Get the MSW register value. */
|
||||
|
@ -1000,8 +1000,8 @@ bignum_divide_start(const uint32_t *dividend,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -1029,7 +1029,7 @@ bignum_divide_get_result(uint32_t *buffer,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
/* Get the MSW register value. */
|
||||
|
|
|
@ -345,10 +345,10 @@ set_poll_mode(uint8_t enable)
|
|||
mac_timer_init();
|
||||
REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_FIFOP; /* mask out FIFOP interrupt source */
|
||||
REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_FIFOP; /* clear pending FIFOP interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_RF_RXTX); /* disable RF interrupts */
|
||||
NVIC_DisableIRQ(RF_TX_RX_IRQn); /* disable RF interrupts */
|
||||
} else {
|
||||
REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; /* enable FIFOP interrupt source */
|
||||
nvic_interrupt_enable(NVIC_INT_RF_RXTX); /* enable RF interrupts */
|
||||
NVIC_EnableIRQ(RF_TX_RX_IRQn); /* enable RF interrupts */
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -516,7 +516,7 @@ init(void)
|
|||
|
||||
/* Acknowledge all RF Error interrupts */
|
||||
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
|
||||
nvic_interrupt_enable(NVIC_INT_RF_ERR);
|
||||
NVIC_EnableIRQ(RF_ERR_IRQn);
|
||||
|
||||
if(CC2538_RF_CONF_TX_USE_DMA) {
|
||||
/* Disable peripheral triggers for the channel */
|
||||
|
|
|
@ -61,8 +61,8 @@ crypto_isr(void)
|
|||
{
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
nvic_interrupt_unpend(NVIC_INT_AES);
|
||||
nvic_interrupt_disable(NVIC_INT_AES);
|
||||
NVIC_ClearPendingIRQ(AES_IRQn);
|
||||
NVIC_DisableIRQ(AES_IRQn);
|
||||
|
||||
if(notification_process != NULL) {
|
||||
process_poll((struct process *)notification_process);
|
||||
|
|
|
@ -152,8 +152,8 @@ ecc_mul_start(uint32_t *scalar, ec_point_t *ec_point,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -181,7 +181,7 @@ ecc_mul_get_result(ec_point_t *ec_point,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
if(REG(PKA_SHIFT) == 0x00000000) {
|
||||
|
@ -319,8 +319,8 @@ ecc_mul_gen_pt_start(uint32_t *scalar, ecc_curve_info_t *curve,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -349,7 +349,7 @@ ecc_mul_gen_pt_get_result(ec_point_t *ec_point,
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
if(REG(PKA_SHIFT) == 0x00000000) {
|
||||
|
@ -492,8 +492,8 @@ ecc_add_start(ec_point_t *ec_point1, ec_point_t *ec_point2,
|
|||
/* Enable Interrupt */
|
||||
if(process != NULL) {
|
||||
pka_register_process_notification(process);
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_enable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_EnableIRQ(PKA_IRQn);
|
||||
}
|
||||
|
||||
return PKA_STATUS_SUCCESS;
|
||||
|
@ -519,7 +519,7 @@ ecc_add_get_result(ec_point_t *ec_point, uint32_t result_vector)
|
|||
}
|
||||
|
||||
/* Disable Interrupt */
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
pka_register_process_notification(NULL);
|
||||
|
||||
if(REG(PKA_SHIFT) == 0x00000000) {
|
||||
|
|
|
@ -100,6 +100,20 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin);
|
|||
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK) \
|
||||
do { REG((PORT_BASE) + GPIO_DIR) |= (PIN_MASK); } while(0)
|
||||
|
||||
/** \brief Return whether pins with PIN_MASK of port with PORT_BASE are set to
|
||||
* output.
|
||||
* \param PORT_BASE GPIO Port register offset
|
||||
* \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80
|
||||
* \return The direction of the pins specified by PIN_MASK
|
||||
*
|
||||
* This macro will \e not return 0 or 1. Instead, it will return the directions
|
||||
* of the pins specified by PIN_MASK ORed together. Thus, if 0xC3
|
||||
* (0x80 | 0x40 | 0x02 | 0x01) is passed as the PIN_MASK and pins 7 and 0 are
|
||||
* set to output, the macro will return 0x81.
|
||||
*/
|
||||
#define GPIO_IS_OUTPUT(PORT_BASE, PIN_MASK) \
|
||||
(REG((PORT_BASE) + GPIO_DIR) & (PIN_MASK))
|
||||
|
||||
/** \brief Set pins with PIN_MASK of port with PORT_BASE high.
|
||||
* \param PORT_BASE GPIO Port register offset
|
||||
* \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80
|
||||
|
|
|
@ -38,74 +38,12 @@
|
|||
*/
|
||||
#include "contiki.h"
|
||||
#include "dev/nvic.h"
|
||||
#include "dev/scb.h"
|
||||
#include "reg.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static uint32_t *interrupt_enable;
|
||||
static uint32_t *interrupt_disable;
|
||||
static uint32_t *interrupt_pend;
|
||||
static uint32_t *interrupt_unpend;
|
||||
#include "cc2538_cm3.h"
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
nvic_init()
|
||||
{
|
||||
interrupt_enable = (uint32_t *)NVIC_EN0;
|
||||
interrupt_disable = (uint32_t *)NVIC_DIS0;
|
||||
interrupt_pend = (uint32_t *)NVIC_PEND0;
|
||||
interrupt_unpend = (uint32_t *)NVIC_UNPEND0;
|
||||
|
||||
/* Provide our interrupt table to the NVIC */
|
||||
REG(SCB_VTABLE) = NVIC_VTABLE_ADDRESS;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
nvic_interrupt_enable(uint32_t intr)
|
||||
{
|
||||
/* Writes of 0 are ignored, which is why we can simply use = */
|
||||
interrupt_enable[intr >> 5] = 1 << (intr & 0x1F);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
nvic_interrupt_disable(uint32_t intr)
|
||||
{
|
||||
/* Writes of 0 are ignored, which is why we can simply use = */
|
||||
interrupt_disable[intr >> 5] = 1 << (intr & 0x1F);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
nvic_interrupt_en_restore(uint32_t intr, uint8_t v)
|
||||
{
|
||||
if(v != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
interrupt_enable[intr >> 5] = 1 << (intr & 0x1F);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint8_t
|
||||
nvic_interrupt_en_save(uint32_t intr)
|
||||
{
|
||||
uint8_t rv = ((interrupt_enable[intr >> 5] & (1 << (intr & 0x1F)))
|
||||
> NVIC_INTERRUPT_DISABLED);
|
||||
|
||||
nvic_interrupt_disable(intr);
|
||||
|
||||
return rv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
nvic_interrupt_pend(uint32_t intr)
|
||||
{
|
||||
/* Writes of 0 are ignored, which is why we can simply use = */
|
||||
interrupt_pend[intr >> 5] = 1 << (intr & 0x1F);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
nvic_interrupt_unpend(uint32_t intr)
|
||||
{
|
||||
/* Writes of 0 are ignored, which is why we can simply use = */
|
||||
interrupt_unpend[intr >> 5] = 1 << (intr & 0x1F);
|
||||
SCB->VTOR = NVIC_VTABLE_ADDRESS;
|
||||
}
|
||||
/** @} */
|
||||
|
|
|
@ -43,14 +43,13 @@
|
|||
#ifndef NVIC_H_
|
||||
#define NVIC_H_
|
||||
|
||||
#include "cc2538_cm3.h"
|
||||
|
||||
#include <stdint.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name NVIC Constants and Configuration
|
||||
* @{
|
||||
*/
|
||||
#define NVIC_INTERRUPT_ENABLED 0x00000001
|
||||
#define NVIC_INTERRUPT_DISABLED 0x00000000
|
||||
|
||||
#ifdef NVIC_CONF_VTABLE_ADDRESS
|
||||
#define NVIC_VTABLE_ADDRESS NVIC_CONF_VTABLE_ADDRESS
|
||||
#else
|
||||
|
@ -59,183 +58,9 @@ extern void(*const vectors[])(void);
|
|||
#endif
|
||||
/** @} */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name NVIC Interrupt assignments
|
||||
* @{
|
||||
*/
|
||||
#define NVIC_INT_GPIO_PORT_A 0 /**< GPIO port A */
|
||||
#define NVIC_INT_GPIO_PORT_B 1 /**< GPIO port B */
|
||||
#define NVIC_INT_GPIO_PORT_C 2 /**< GPIO port C */
|
||||
#define NVIC_INT_GPIO_PORT_D 3 /**< GPIO port D */
|
||||
#define NVIC_INT_UART0 5 /**< UART0 */
|
||||
#define NVIC_INT_UART1 6 /**< UART1 */
|
||||
#define NVIC_INT_SSI0 7 /**< SSI0 */
|
||||
#define NVIC_INT_I2C 8 /**< I2C */
|
||||
#define NVIC_INT_ADC 14 /**< ADC */
|
||||
#define NVIC_INT_WDT 18 /**< Watchdog Timer */
|
||||
#define NVIC_INT_GPTIMER_0A 19 /**< GPTimer 0A */
|
||||
#define NVIC_INT_GPTIMER_0B 20 /**< GPTimer 0B */
|
||||
#define NVIC_INT_GPTIMER_1A 21 /**< GPTimer 1A */
|
||||
#define NVIC_INT_GPTIMER_1B 22 /**< GPTimer 1B */
|
||||
#define NVIC_INT_GPTIMER_2A 23 /**< GPTimer 2A */
|
||||
#define NVIC_INT_GPTIMER_2B 24 /**< GPTimer 2B */
|
||||
#define NVIC_INT_ADC_CMP 25 /**< Analog Comparator */
|
||||
#define NVIC_INT_RF_RXTX_ALT 26 /**< RF TX/RX (Alternate) */
|
||||
#define NVIC_INT_RF_ERR_ALT 27 /**< RF Error (Alternate) */
|
||||
#define NVIC_INT_SYS_CTRL 28 /**< System Control */
|
||||
#define NVIC_INT_FLASH_CTRL 29 /**< Flash memory control */
|
||||
#define NVIC_INT_AES_ALT 30 /**< AES (Alternate) */
|
||||
#define NVIC_INT_PKA_ALT 31 /**< PKA (Alternate) */
|
||||
#define NVIC_INT_SM_TIMER_ALT 32 /**< SM Timer (Alternate) */
|
||||
#define NVIC_INT_MAC_TIMER_ALT 33 /**< MAC Timer (Alternate) */
|
||||
#define NVIC_INT_SSI1 34 /**< SSI1 */
|
||||
#define NVIC_INT_GPTIMER_3A 35 /**< GPTimer 3A */
|
||||
#define NVIC_INT_GPTIMER_3B 36 /**< GPTimer 3B */
|
||||
#define NVIC_INT_UDMA 46 /**< uDMA software */
|
||||
#define NVIC_INT_UDMA_ERR 47 /**< uDMA error */
|
||||
#define NVIC_INT_USB 140 /**< USB */
|
||||
#define NVIC_INT_RF_RXTX 141 /**< RF Core Rx/Tx */
|
||||
#define NVIC_INT_RF_ERR 142 /**< RF Core Error */
|
||||
#define NVIC_INT_AES 143 /**< AES */
|
||||
#define NVIC_INT_PKA 144 /**< PKA */
|
||||
#define NVIC_INT_SM_TIMER 145 /**< SM Timer */
|
||||
#define NVIC_INT_MACTIMER 146 /**< MAC Timer */
|
||||
/** @} */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name NVIC Register Declarations
|
||||
* @{
|
||||
*/
|
||||
#define NVIC_EN0 0xE000E100 /**< Interrupt 0-31 Set Enable */
|
||||
#define NVIC_EN1 0xE000E104 /**< Interrupt 32-54 Set Enable */
|
||||
#define NVIC_EN2 0xE000E108 /**< Interrupt 64-95 Set Enable */
|
||||
#define NVIC_EN3 0xE000E10C /**< Interrupt 96-127 Set Enable */
|
||||
#define NVIC_EN4 0xE000E110 /**< Interrupt 128-131 Set Enable */
|
||||
#define NVIC_DIS0 0xE000E180 /**< Interrupt 0-31 Clear Enable */
|
||||
#define NVIC_DIS1 0xE000E184 /**< Interrupt 32-54 Clear Enable */
|
||||
#define NVIC_DIS2 0xE000E188 /**< Interrupt 64-95 Clear Enable */
|
||||
#define NVIC_DIS3 0xE000E18C /**< Interrupt 96-127 Clear Enable */
|
||||
#define NVIC_DIS4 0xE000E190 /**< Interrupt 128-131 Clear Enable */
|
||||
#define NVIC_PEND0 0xE000E200 /**< Interrupt 0-31 Set Pending */
|
||||
#define NVIC_PEND1 0xE000E204 /**< Interrupt 32-54 Set Pending */
|
||||
#define NVIC_PEND2 0xE000E208 /**< Interrupt 64-95 Set Pending */
|
||||
#define NVIC_PEND3 0xE000E20C /**< Interrupt 96-127 Set Pending */
|
||||
#define NVIC_PEND4 0xE000E210 /**< Interrupt 128-131 Set Pending */
|
||||
#define NVIC_UNPEND0 0xE000E280 /**< Interrupt 0-31 Clear Pending */
|
||||
#define NVIC_UNPEND1 0xE000E284 /**< Interrupt 32-54 Clear Pending */
|
||||
#define NVIC_UNPEND2 0xE000E288 /**< Interrupt 64-95 Clear Pending */
|
||||
#define NVIC_UNPEND3 0xE000E28C /**< Interrupt 96-127 Clear Pending */
|
||||
#define NVIC_UNPEND4 0xE000E290 /**< Interrupt 128-131 Clear Pending */
|
||||
#define NVIC_ACTIVE0 0xE000E300 /**< Interrupt 0-31 Active Bit */
|
||||
#define NVIC_ACTIVE1 0xE000E304 /**< Interrupt 32-54 Active Bit */
|
||||
#define NVIC_ACTIVE2 0xE000E308 /**< Interrupt 64-95 Active Bit */
|
||||
#define NVIC_ACTIVE3 0xE000E30C /**< Interrupt 96-127 Active Bit */
|
||||
#define NVIC_ACTIVE4 0xE000E310 /**< Interrupt 128-131 Active Bit */
|
||||
#define NVIC_PRI0 0xE000E400 /**< Interrupt 0-3 Priority */
|
||||
#define NVIC_PRI1 0xE000E404 /**< Interrupt 4-7 Priority */
|
||||
#define NVIC_PRI2 0xE000E408 /**< Interrupt 8-11 Priority */
|
||||
#define NVIC_PRI3 0xE000E40C /**< Interrupt 12-15 Priority */
|
||||
#define NVIC_PRI4 0xE000E410 /**< Interrupt 16-19 Priority */
|
||||
#define NVIC_PRI5 0xE000E414 /**< Interrupt 20-23 Priority */
|
||||
#define NVIC_PRI6 0xE000E418 /**< Interrupt 24-27 Priority */
|
||||
#define NVIC_PRI7 0xE000E41C /**< Interrupt 28-31 Priority */
|
||||
#define NVIC_PRI8 0xE000E420 /**< Interrupt 32-35 Priority */
|
||||
#define NVIC_PRI9 0xE000E424 /**< Interrupt 36-39 Priority */
|
||||
#define NVIC_PRI10 0xE000E428 /**< Interrupt 40-43 Priority */
|
||||
#define NVIC_PRI11 0xE000E42C /**< Interrupt 44-47 Priority */
|
||||
#define NVIC_PRI12 0xE000E430 /**< Interrupt 48-51 Priority */
|
||||
#define NVIC_PRI13 0xE000E434 /**< Interrupt 52-53 Priority */
|
||||
#define NVIC_PRI14 0xE000E438 /**< Interrupt 56-59 Priority */
|
||||
#define NVIC_PRI15 0xE000E43C /**< Interrupt 60-63 Priority */
|
||||
#define NVIC_PRI16 0xE000E440 /**< Interrupt 64-67 Priority */
|
||||
#define NVIC_PRI17 0xE000E444 /**< Interrupt 68-71 Priority */
|
||||
#define NVIC_PRI18 0xE000E448 /**< Interrupt 72-75 Priority */
|
||||
#define NVIC_PRI19 0xE000E44C /**< Interrupt 76-79 Priority */
|
||||
#define NVIC_PRI20 0xE000E450 /**< Interrupt 80-83 Priority */
|
||||
#define NVIC_PRI21 0xE000E454 /**< Interrupt 84-87 Priority */
|
||||
#define NVIC_PRI22 0xE000E458 /**< Interrupt 88-91 Priority */
|
||||
#define NVIC_PRI23 0xE000E45C /**< Interrupt 92-95 Priority */
|
||||
#define NVIC_PRI24 0xE000E460 /**< Interrupt 96-99 Priority */
|
||||
#define NVIC_PRI25 0xE000E464 /**< Interrupt 100-103 Priority */
|
||||
#define NVIC_PRI26 0xE000E468 /**< Interrupt 104-107 Priority */
|
||||
#define NVIC_PRI27 0xE000E46C /**< Interrupt 108-111 Priority */
|
||||
#define NVIC_PRI28 0xE000E470 /**< Interrupt 112-115 Priority */
|
||||
#define NVIC_PRI29 0xE000E474 /**< Interrupt 116-119 Priority */
|
||||
#define NVIC_PRI30 0xE000E478 /**< Interrupt 120-123 Priority */
|
||||
#define NVIC_PRI31 0xE000E47C /**< Interrupt 124-127 Priority */
|
||||
#define NVIC_PRI32 0xE000E480 /**< Interrupt 128-131 Priority */
|
||||
#define NVIC_PRI33 0xE000E480 /**< Interrupt 132-135 Priority */
|
||||
#define NVIC_PRI34 0xE000E484 /**< Interrupt 136-139 Priority */
|
||||
#define NVIC_PRI35 0xE000E488 /**< Interrupt 140-143 Priority */
|
||||
#define NVIC_PRI36 0xE000E48c /**< Interrupt 144-147 Priority */
|
||||
/** @} */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \brief Initialises the NVIC driver */
|
||||
void nvic_init();
|
||||
|
||||
/**
|
||||
* \brief Enables interrupt intr
|
||||
* \param intr The interrupt number (NOT the vector number). For example,
|
||||
* GPIO Port A interrupt is 0, not 16.
|
||||
*
|
||||
* Possible values for the \e intr param are defined as NVIC_INT_xyz. For
|
||||
* instance, to enable the GPIO Port A interrupt, pass NVIC_INT_GPIO_PORT_A
|
||||
*/
|
||||
void nvic_interrupt_enable(uint32_t intr);
|
||||
|
||||
/**
|
||||
* \brief Disables interrupt intr
|
||||
* \param intr The interrupt number (NOT the vector number). For example,
|
||||
* GPIO Port A interrupt is 0, not 16.
|
||||
*
|
||||
* Possible values for the \e intr param are defined as NVIC_INT_xyz. For
|
||||
* instance, to disable the GPIO Port A interrupt, pass NVIC_INT_GPIO_PORT_A
|
||||
*/
|
||||
void nvic_interrupt_disable(uint32_t intr);
|
||||
|
||||
/**
|
||||
* \brief Enables interrupt intr if v > 0
|
||||
* \param intr The interrupt number (NOT the vector number). For example,
|
||||
* GPIO Port A interrupt is 0, not 16.
|
||||
* \param v 0: No effect, 1: Enables the interrupt
|
||||
*
|
||||
* This function is useful to restore an interrupt to a state previously
|
||||
* saved by nvic_interrupt_en_save. Thus, if when nvic_interrupt_en_save was
|
||||
* called the interrupt was enabled, this function will re-enabled it.
|
||||
* Possible values for the \e intr param are defined as NVIC_INT_xyz. For
|
||||
* instance, to disable the GPIO Port A interrupt, pass NVIC_INT_GPIO_PORT_A
|
||||
*/
|
||||
void nvic_interrupt_en_restore(uint32_t intr, uint8_t v);
|
||||
|
||||
/**
|
||||
* \brief Checks the interrupt enabled status for intr
|
||||
* \param intr The interrupt number (NOT the vector number). For example,
|
||||
* GPIO Port A interrupt is 0, not 16.
|
||||
* \return 1: Enabled, 0: Disabled
|
||||
*
|
||||
* Possible values for the \e intr param are defined as NVIC_INT_xyz. For
|
||||
* instance, to disable the GPIO Port A interrupt, pass NVIC_INT_GPIO_PORT_A
|
||||
*/
|
||||
uint8_t nvic_interrupt_en_save(uint32_t intr);
|
||||
|
||||
/**
|
||||
* \brief Sets intr to pending
|
||||
* \param intr The interrupt number (NOT the vector number). For example,
|
||||
* GPIO Port A interrupt is 0, not 16.
|
||||
*
|
||||
* Possible values for the \e intr param are defined as NVIC_INT_xyz. For
|
||||
* instance, to enable the GPIO Port A interrupt, pass NVIC_INT_GPIO_PORT_A
|
||||
*/
|
||||
void nvic_interrupt_pend(uint32_t intr);
|
||||
|
||||
/**
|
||||
* \brief Sets intr to no longer pending
|
||||
* \param intr The interrupt number (NOT the vector number). For example,
|
||||
* GPIO Port A interrupt is 0, not 16.
|
||||
*
|
||||
* Possible values for the \e intr param are defined as NVIC_INT_xyz. For
|
||||
* instance, to disable the GPIO Port A interrupt, pass NVIC_INT_GPIO_PORT_A
|
||||
*/
|
||||
void nvic_interrupt_unpend(uint32_t intr);
|
||||
|
||||
#endif /* NVIC_H_ */
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,8 +64,8 @@ pka_isr(void)
|
|||
{
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
nvic_interrupt_unpend(NVIC_INT_PKA);
|
||||
nvic_interrupt_disable(NVIC_INT_PKA);
|
||||
NVIC_ClearPendingIRQ(PKA_IRQn);
|
||||
NVIC_DisableIRQ(PKA_IRQn);
|
||||
|
||||
if(notification_process != NULL) {
|
||||
process_poll((struct process *)notification_process);
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/
|
||||
* 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.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup cc2538
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc2538-scb cc2538 System Control Block (SCB)
|
||||
*
|
||||
* Offsets and bit definitions for SCB registers
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
* Header file for the System Control Block (SCB)
|
||||
*/
|
||||
#ifndef SCB_H_
|
||||
#define SCB_H_
|
||||
|
||||
#define SCB_CPUID 0xE000ED00 /**< CPU ID Base */
|
||||
#define SCB_INTCTRL 0xE000ED04 /**< Interrupt Control and State */
|
||||
#define SCB_VTABLE 0xE000ED08 /**< Vector Table Offset */
|
||||
#define SCB_APINT 0xE000ED0C /**< Application Interrupt and Reset Control */
|
||||
#define SCB_SYSCTRL 0xE000ED10 /**< System Control */
|
||||
#define SCB_CFGCTRL 0xE000ED14 /**< Configuration and Control */
|
||||
#define SCB_SYSPRI1 0xE000ED18 /**< System Handler Priority 1 */
|
||||
#define SCB_SYSPRI2 0xE000ED1C /**< System Handler Priority 2 */
|
||||
#define SCB_SYSPRI3 0xE000ED20 /**< System Handler Priority 3 */
|
||||
#define SCB_SYSHNDCTRL 0xE000ED24 /**< System Handler Control and State */
|
||||
#define SCB_FAULTSTAT 0xE000ED28 /**< Configurable Fault Status */
|
||||
#define SCB_HFAULTSTAT 0xE000ED2C /**< Hard Fault Status */
|
||||
#define SCB_DEBUG_STAT 0xE000ED30 /**< Debug Status Register */
|
||||
#define SCB_MMADDR 0xE000ED34 /**< Memory Management Fault Address */
|
||||
#define SCB_FAULT_ADDR 0xE000ED38 /**< Bus Fault Address */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name VTABLE register bits
|
||||
* @{
|
||||
*/
|
||||
#define SCB_VTABLE_BASE 0x20000000 /**< Vector Table Base */
|
||||
#define SCB_VTABLE_OFFSET_M 0x1FFFFE00 /**< Vector Table Offset */
|
||||
/** @} */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name SCB_SYSCTRL register bits
|
||||
* @{
|
||||
*/
|
||||
#define SCB_SYSCTRL_SEVONPEND 0x00000010 /**< Wake up on pending */
|
||||
#define SCB_SYSCTRL_SLEEPDEEP 0x00000004 /**< Deep sleep enable */
|
||||
#define SCB_SYSCTRL_SLEEPEXIT 0x00000002 /**< Sleep on ISR exit */
|
||||
/** @} */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif /* SCB_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -40,6 +40,7 @@
|
|||
#include "contiki.h"
|
||||
#include "reg.h"
|
||||
#include "spi-arch.h"
|
||||
#include "sys/cc.h"
|
||||
#include "dev/ioc.h"
|
||||
#include "dev/sys-ctrl.h"
|
||||
#include "dev/spi.h"
|
||||
|
@ -155,7 +156,12 @@
|
|||
#if (SPI1_CPRS_CPSDVSR & 1) == 1 || SPI1_CPRS_CPSDVSR < 2 || SPI1_CPRS_CPSDVSR > 254
|
||||
#error SPI1_CPRS_CPSDVSR must be an even number between 2 and 254
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Clock source from which the baud clock is determined for the SSI, according
|
||||
* to SSI_CC.CS.
|
||||
*/
|
||||
#define SSI_SYS_CLOCK SYS_CTRL_SYS_CLOCK
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
int8_t port;
|
||||
|
@ -314,6 +320,37 @@ spix_set_mode(uint8_t spi,
|
|||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
spix_set_clock_freq(uint8_t spi, uint32_t freq)
|
||||
{
|
||||
const spi_regs_t *regs;
|
||||
uint64_t div;
|
||||
uint32_t scr;
|
||||
|
||||
if(spi >= SSI_INSTANCE_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
regs = &spi_regs[spi];
|
||||
|
||||
/* Disable the SSI peripheral to configure it */
|
||||
REG(regs->base + SSI_CR1) = 0;
|
||||
|
||||
/* Configure the SSI serial clock rate */
|
||||
if(!freq) {
|
||||
scr = 255;
|
||||
} else {
|
||||
div = (uint64_t)regs->ssi_cprs_cpsdvsr * freq;
|
||||
scr = (SSI_SYS_CLOCK + div - 1) / div;
|
||||
scr = MIN(MAX(scr, 1), 256) - 1;
|
||||
}
|
||||
REG(regs->base + SSI_CR0) = (REG(regs->base + SSI_CR0) & ~SSI_CR0_SCR_M) |
|
||||
scr << SSI_CR0_SCR_S;
|
||||
|
||||
/* Re-enable the SSI */
|
||||
REG(regs->base + SSI_CR1) |= SSI_CR1_SSE;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
spix_cs_init(uint8_t port, uint8_t pin)
|
||||
{
|
||||
GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port),
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
*/
|
||||
#define SSI0_BASE 0x40008000 /**< Base address for SSI0 */
|
||||
#define SSI1_BASE 0x40009000 /**< Base address for SSI1 */
|
||||
/** Base address of the \c dev instance of the SSI */
|
||||
#define SSI_BASE(dev) (SSI0_BASE + (dev) * (SSI1_BASE - SSI0_BASE))
|
||||
/** @} */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name SSI register offsets
|
||||
|
|
|
@ -181,7 +181,7 @@ static const uart_regs_t uart_regs[UART_INSTANCE_COUNT] = {
|
|||
.tx = {UART0_TX_PORT, UART0_TX_PIN},
|
||||
.cts = {-1, -1},
|
||||
.rts = {-1, -1},
|
||||
.nvic_int = NVIC_INT_UART0
|
||||
.nvic_int = UART0_IRQn
|
||||
}, {
|
||||
.sys_ctrl_rcgcuart_uart = SYS_CTRL_RCGCUART_UART1,
|
||||
.sys_ctrl_scgcuart_uart = SYS_CTRL_SCGCUART_UART1,
|
||||
|
@ -195,7 +195,7 @@ static const uart_regs_t uart_regs[UART_INSTANCE_COUNT] = {
|
|||
.tx = {UART1_TX_PORT, UART1_TX_PIN},
|
||||
.cts = {UART1_CTS_PORT, UART1_CTS_PIN},
|
||||
.rts = {UART1_RTS_PORT, UART1_RTS_PIN},
|
||||
.nvic_int = NVIC_INT_UART1
|
||||
.nvic_int = UART1_IRQn
|
||||
}
|
||||
};
|
||||
static int (* input_handler[UART_INSTANCE_COUNT])(unsigned char c);
|
||||
|
@ -328,7 +328,7 @@ uart_init(uint8_t uart)
|
|||
REG(regs->base + UART_CTL) |= UART_CTL_UARTEN;
|
||||
|
||||
/* Enable UART0 Interrupts */
|
||||
nvic_interrupt_enable(regs->nvic_int);
|
||||
NVIC_EnableIRQ(regs->nvic_int);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
|
|
|
@ -62,8 +62,8 @@ udma_init()
|
|||
|
||||
REG(UDMA_CTLBASE) = (uint32_t)(&channel_config);
|
||||
|
||||
nvic_interrupt_enable(NVIC_INT_UDMA);
|
||||
nvic_interrupt_enable(NVIC_INT_UDMA_ERR);
|
||||
NVIC_EnableIRQ(UDMA_SW_IRQn);
|
||||
NVIC_EnableIRQ(UDMA_ERR_IRQn);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
#include "sys/energest.h"
|
||||
#include "sys/process.h"
|
||||
#include "dev/sys-ctrl.h"
|
||||
#include "dev/scb.h"
|
||||
#include "dev/rfcore-xreg.h"
|
||||
#include "rtimer-arch.h"
|
||||
#include "lpm.h"
|
||||
#include "cc2538_cm3.h"
|
||||
#include "reg.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
@ -379,7 +379,7 @@ lpm_init()
|
|||
* By default, we will enter PM0 unless lpm_enter() decides otherwise
|
||||
*/
|
||||
REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM0;
|
||||
REG(SCB_SYSCTRL) |= SCB_SYSCTRL_SLEEPDEEP;
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
max_pm = LPM_CONF_MAX_PM;
|
||||
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Loughborough University - Computer Science
|
||||
* 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.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* \file
|
||||
* Stub header file for multi-threading. It doesn't do anything, it
|
||||
* just exists so that mt.c can compile cleanly.
|
||||
*
|
||||
* This is based on the original mtarch.h for z80 by Takahide Matsutsuka
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
#ifndef MTARCH_H_
|
||||
#define MTARCH_H_
|
||||
|
||||
struct mtarch_thread {
|
||||
unsigned char *sp;
|
||||
};
|
||||
|
||||
#endif /* MTARCH_H_ */
|
|
@ -99,7 +99,7 @@ rtimer_arch_schedule(rtimer_clock_t t)
|
|||
/* Store the value. The LPM module will query us for it */
|
||||
next_trigger = t;
|
||||
|
||||
nvic_interrupt_enable(NVIC_INT_SM_TIMER);
|
||||
NVIC_EnableIRQ(SMT_IRQn);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rtimer_clock_t
|
||||
|
@ -147,8 +147,8 @@ rtimer_isr()
|
|||
|
||||
next_trigger = 0;
|
||||
|
||||
nvic_interrupt_unpend(NVIC_INT_SM_TIMER);
|
||||
nvic_interrupt_disable(NVIC_INT_SM_TIMER);
|
||||
NVIC_ClearPendingIRQ(SMT_IRQn);
|
||||
NVIC_DisableIRQ(SMT_IRQn);
|
||||
|
||||
rtimer_run_next();
|
||||
|
||||
|
|
|
@ -109,17 +109,17 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* New API macros */
|
||||
#define SPIX_WAITFORTxREADY(spi) do { \
|
||||
while(!(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_TNF)) ; \
|
||||
while(!(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_TNF)) ; \
|
||||
} while(0)
|
||||
#define SPIX_BUF(spi) REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_DR)
|
||||
#define SPIX_BUF(spi) REG(SSI_BASE(spi) + SSI_DR)
|
||||
#define SPIX_WAITFOREOTx(spi) do { \
|
||||
while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_BSY) ; \
|
||||
while(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_BSY) ; \
|
||||
} while(0)
|
||||
#define SPIX_WAITFOREORx(spi) do { \
|
||||
while(!(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_RNE)) ; \
|
||||
while(!(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_RNE)) ; \
|
||||
} while(0)
|
||||
#define SPIX_FLUSH(spi) do { \
|
||||
while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_RNE) { \
|
||||
while(REG(SSI_BASE(spi) + SSI_SR) & SSI_SR_RNE) { \
|
||||
SPIX_BUF(spi); \
|
||||
} \
|
||||
} while(0)
|
||||
|
@ -197,6 +197,14 @@ void spix_set_mode(uint8_t spi, uint32_t frame_format,
|
|||
uint32_t clock_polarity, uint32_t clock_phase,
|
||||
uint32_t data_size);
|
||||
|
||||
/**
|
||||
* \brief Sets the SPI clock frequency of the given SSI instance.
|
||||
*
|
||||
* \param spi SSI instance
|
||||
* \param freq Frequency (Hz)
|
||||
*/
|
||||
void spix_set_clock_freq(uint8_t spi, uint32_t freq);
|
||||
|
||||
/**
|
||||
* \brief Configure a GPIO to be the chip select pin.
|
||||
*
|
||||
|
|
|
@ -52,6 +52,8 @@ void nmi_handler(void);
|
|||
void default_handler(void);
|
||||
|
||||
/* System Handler and ISR prototypes implemented elsewhere */
|
||||
void svcall_handler(void); /* See mtarch.c */
|
||||
void pendsv_handler(void); /* See mtarch.c */
|
||||
void clock_isr(void); /* SysTick Handler */
|
||||
void gpio_port_a_isr(void);
|
||||
void gpio_port_b_isr(void);
|
||||
|
@ -119,10 +121,10 @@ void(*const vectors[])(void) =
|
|||
0, /* 8 Reserved */
|
||||
0, /* 9 Reserved */
|
||||
0, /* 10 Reserved */
|
||||
default_handler, /* 11 SVCall handler */
|
||||
svcall_handler, /* 11 SVCall handler */
|
||||
default_handler, /* 12 Debug monitor handler */
|
||||
0, /* 13 Reserved */
|
||||
default_handler, /* 14 The PendSV handler */
|
||||
pendsv_handler, /* 14 The PendSV handler */
|
||||
clock_isr, /* 15 The SysTick handler */
|
||||
gpio_port_a_isr, /* 16 GPIO Port A */
|
||||
gpio_port_b_isr, /* 17 GPIO Port B */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue