You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2015/12/10 01:57:02 UTC
[1/2] incubator-mynewt-larva git commit: Implement data length change
procedure. Now the advertiser does not stop advertising after 60 seconds.
Advertising will end only if there is a connection
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master 1d324a773 -> 05254c74c
Implement data length change procedure. Now the advertiser does not stop advertising after 60 seconds. Advertising will end only if there is a connection
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/05254c74
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/05254c74
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/05254c74
Branch: refs/heads/master
Commit: 05254c74ca8854d6d8f2d595ec35c2f17fed7770
Parents: acbd147
Author: wes3 <wi...@micosa.io>
Authored: Wed Dec 9 16:56:50 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Wed Dec 9 16:56:56 2015 -0800
----------------------------------------------------------------------
.../controller/include/controller/ble_ll.h | 26 +-
.../controller/include/controller/ble_ll_conn.h | 14 +-
.../controller/include/controller/ble_ll_ctrl.h | 7 +-
net/nimble/controller/src/ble_ll.c | 48 ++-
net/nimble/controller/src/ble_ll_conn.c | 122 +++++--
net/nimble/controller/src/ble_ll_ctrl.c | 320 +++++++++++++++++--
net/nimble/controller/src/ble_ll_hci.c | 1 +
net/nimble/host/src/host_dbg.c | 8 +-
project/bletest/src/main.c | 19 +-
9 files changed, 481 insertions(+), 84 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index d532987..64ee545 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -32,6 +32,9 @@ struct ble_ll_obj
/* Current Link Layer state */
uint8_t ll_state;
+ /* Supported features */
+ uint8_t ll_supp_features;
+
/* Task event queue */
struct os_eventq ll_evq;
@@ -56,9 +59,11 @@ struct ble_ll_stats
uint32_t hci_cmd_errs;
uint32_t hci_events_sent;
uint32_t bad_ll_state;
- uint32_t rx_crc_ok;
- uint32_t rx_crc_fail;
uint32_t rx_bytes;
+ uint32_t rx_valid_adv_pdus;
+ uint32_t rx_invalid_adv_pdus;
+ uint32_t rx_adv_malformed_pkts;
+ uint32_t rx_adv_unk_pdu_type;
uint32_t rx_adv_ind;
uint32_t rx_adv_direct_ind;
uint32_t rx_adv_nonconn_ind;
@@ -66,8 +71,17 @@ struct ble_ll_stats
uint32_t rx_scan_rsps;
uint32_t rx_connect_reqs;
uint32_t rx_scan_ind;
- uint32_t rx_unk_pdu;
- uint32_t rx_malformed_pkts;
+ uint32_t rx_unk_pdus;
+ uint32_t rx_valid_data_pdus;
+ uint32_t rx_invalid_data_pdus;
+ uint32_t rx_ctrl_pdus;
+ uint32_t rx_l2cap_pdus;
+ uint32_t rx_malformed_ctrl_pdus;
+ uint32_t rx_bad_llid;
+ uint32_t tx_ctrl_pdus;
+ uint32_t tx_ctrl_bytes;
+ uint32_t tx_data_pdus;
+ uint32_t tx_data_bytes;
};
extern struct ble_ll_stats g_ble_ll_stats;
@@ -269,6 +283,9 @@ void ble_ll_wfr_enable(uint32_t cputime, ble_ll_wfr_func wfr_cb, void *arg);
/* Disable wait for response timer */
void ble_ll_wfr_disable(void);
+/* Read set of features supported by the Link Layer */
+uint8_t ble_ll_read_supp_features(void);
+
/*
* XXX: temporary LL debug log. Will get removed once we transition to real
* log
@@ -291,4 +308,5 @@ void ble_ll_log(uint8_t id, uint8_t arg0_8, uint8_t arg1_8, uint32_t arg0_32);
#define ble_ll_log(m,n,o,p)
#endif
+
#endif /* H_LL_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index 8aae9d3..6b61c6d 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -33,6 +33,12 @@
#define BLE_MASTER_SCA_21_30_PPM (6)
#define BLE_MASTER_SCA_0_20_PPM (7)
+/* Definitions for max rx/tx time/bytes for connections */
+#define BLE_LL_CONN_SUPP_TIME_MIN (328) /* usecs */
+#define BLE_LL_CONN_SUPP_TIME_MAX (2120) /* usecs */
+#define BLE_LL_CONN_SUPP_BYTES_MIN (27) /* bytes */
+#define BLE_LL_CONN_SUPP_BYTES_MAX (251) /* bytes */
+
/*
* Length of empty pdu mbuf. Each connection state machine contains an
* empty pdu since we dont want to allocate a full mbuf for an empty pdu
@@ -131,11 +137,12 @@ struct ble_ll_conn_sm
/* empty pdu for connection */
uint32_t conn_empty_pdu[BLE_LL_EMPTY_PDU_MBUF_SIZE];
- /* LL control procedure timer */
- struct os_callout_func ctrl_proc_timer;
+ /* LL control procedure response timer */
+ struct os_callout_func ctrl_proc_rsp_timer;
};
/* API */
+struct ble_ll_len_req;
int ble_ll_conn_create(uint8_t *cmdbuf);
int ble_ll_conn_create_cancel(void);
int ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva);
@@ -152,5 +159,8 @@ void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok);
void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len);
void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om);
+void ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm,
+ struct ble_ll_len_req *req);
+
#endif /* H_BLE_LL_CONN_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/controller/include/controller/ble_ll_ctrl.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_ctrl.h b/net/nimble/controller/include/controller/ble_ll_ctrl.h
index 4a24cac..1382f8c 100644
--- a/net/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/net/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -31,6 +31,7 @@
#define BLE_LL_CTRL_PROC_CONN_PARAM_REQ (6)
#define BLE_LL_CRTL_PROC_LE_PING (7)
#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8)
+#define BLE_LL_CTRL_PROC_NUM (9)
#define BLE_LL_CTRL_PROC_IDLE (255)
/*
@@ -61,6 +62,9 @@
#define BLE_LL_CTRL_LENGTH_REQ (20)
#define BLE_LL_CTRL_LENGTH_RSP (21)
+/* Maximum # of payload bytes in a LL control PDU */
+#define BLE_LL_CTRL_MAX_PAYLOAD (26)
+
/* LL control connection update request */
struct ble_ll_conn_upd_req
{
@@ -207,6 +211,7 @@ struct ble_ll_len_req
void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
void ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc);
void ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om);
-
+void ble_ll_ctrl_datalen_chg_event(struct ble_ll_conn_sm *connsm);
+void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm);
#endif /* H_BLE_LL_CTRL_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c
index 98006b3..667150c 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -52,9 +52,15 @@
* 2) Need to figure out what to do with packets that we hand up that did
* not pass the filter policy for the given state. Currently I count all
* packets I think. Need to figure out what to do with this.
+ * 3) For the features defined, we need to conditionally compile code.
*
*/
+/* Configuration for supported features */
+#define BLE_LL_CFG_FEAT_DATA_LEN_EXT
+#undef BLE_LL_CFG_FEAT_LE_ENCRYPTION
+#undef BLE_LL_CFG_FEAT_EXT_REJECT_IND
+
/* The global BLE LL data object */
struct ble_ll_obj g_ble_ll_data;
@@ -140,7 +146,7 @@ ble_ll_count_rx_adv_pdus(uint8_t pdu_type)
++g_ble_ll_stats.rx_scan_ind;
break;
default:
- ++g_ble_ll_stats.rx_unk_pdu;
+ ++g_ble_ll_stats.rx_adv_unk_pdu_type;
break;
}
}
@@ -252,13 +258,15 @@ ble_ll_is_our_devaddr(uint8_t *addr, int addr_type)
/**
* ll pdu tx time get
*
- * Returns the number of usecs it will take to transmit a PDU of length 'len'
- * bytes. Each byte takes 8 usecs.
+ * Returns the number of usecs it will take to transmit a PDU of length 'len'
+ * bytes. Each byte takes 8 usecs. This routine includes the LL overhead:
+ * preamble (1), access addr (4) and crc (3) for a total of 8 bytes.
*
- * @param len The number of PDU bytes to transmit
+ * @param len The number of PDU bytes to transmit. This includes both header
+ * and payload.
*
- * @return uint16_t The number of usecs it will take to transmit a PDU of
- * length 'len' bytes.
+ * @return uint16_t The number of usecs it will take to transmit a PDU of
+ * length 'len' bytes.
*/
uint16_t
ble_ll_pdu_tx_time_get(uint16_t len)
@@ -390,15 +398,14 @@ ble_ll_rx_pkt_in_proc(void)
if (ble_hdr->crcok) {
/* The total bytes count the PDU header and PDU payload */
g_ble_ll_stats.rx_bytes += pkthdr->omp_len;
- ++g_ble_ll_stats.rx_crc_ok;
- } else {
- ++g_ble_ll_stats.rx_crc_fail;
}
if (ble_hdr->channel < BLE_PHY_NUM_DATA_CHANS) {
ble_ll_conn_rx_data_pdu(m, ble_hdr->crcok);
} else {
if (ble_hdr->crcok) {
+ ++g_ble_ll_stats.rx_valid_adv_pdus;
+
/* Get advertising PDU type */
pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
ble_ll_count_rx_adv_pdus(pdu_type);
@@ -429,6 +436,8 @@ ble_ll_rx_pkt_in_proc(void)
assert(0);
break;
}
+ } else {
+ ++g_ble_ll_stats.rx_invalid_adv_pdus;
}
/* Free the packet buffer */
@@ -638,7 +647,7 @@ ble_ll_rx_end(struct os_mbuf *rxpdu, uint8_t chan, uint8_t crcok)
/* If this is a malformed packet, just kill it here */
if (badpkt) {
- ++g_ble_ll_stats.rx_malformed_pkts;
+ ++g_ble_ll_stats.rx_adv_malformed_pkts;
os_mbuf_free(rxpdu);
return -1;
}
@@ -758,6 +767,17 @@ ble_ll_event_send(struct os_event *ev)
}
/**
+ * Returns the features supported by the link layer
+ *
+ * @return uint8_t bitmask of supported features.
+ */
+uint8_t
+ble_ll_read_supp_features(void)
+{
+ return g_ble_ll_data.ll_supp_features;
+}
+
+/**
* Initialize the Link Layer. Should be called only once
*
* @return int
@@ -765,6 +785,7 @@ ble_ll_event_send(struct os_event *ev)
int
ble_ll_init(void)
{
+ uint8_t features;
struct ble_ll_obj *lldata;
/* Get pointer to global data object */
@@ -800,6 +821,13 @@ ble_ll_init(void)
/* Initialize the connection module */
ble_ll_conn_init();
+ /* Set the supported features */
+ features = 0;
+#ifdef BLE_LL_CFG_FEAT_DATA_LEN_EXT
+ features |= BLE_LL_FEAT_DATA_LEN_EXT;
+#endif
+ lldata->ll_supp_features = features;
+
/* Initialize the LL task */
os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL, BLE_LL_TASK_PRI,
OS_WAIT_FOREVER, g_ble_ll_stack, BLE_LL_STACK_SIZE);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 548a116..c86b659 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -82,8 +82,8 @@ extern int ble_hs_rx_data(struct os_mbuf *om);
#define BLE_LL_CONN_CFG_OUR_SCA (500) /* in ppm */
/* LL configuration definitions */
-#define BLE_LL_CFG_SUPP_MAX_RX_BYTES (27)
-#define BLE_LL_CFG_SUPP_MAX_TX_BYTES (27)
+#define BLE_LL_CFG_SUPP_MAX_RX_BYTES (251)
+#define BLE_LL_CFG_SUPP_MAX_TX_BYTES (251)
#define BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES (27)
/* Roles */
@@ -96,10 +96,6 @@ extern int ble_hs_rx_data(struct os_mbuf *om);
#define BLE_LL_CONN_STATE_CREATED (1)
#define BLE_LL_CONN_STATE_ESTABLISHED (2)
-/* Data Lenth Procedure */
-#define BLE_LL_CONN_SUPP_TIME_MIN (328) /* usecs */
-#define BLE_LL_CONN_SUPP_BYTES_MIN (27) /* bytes */
-
/* Connection request */
#define BLE_LL_CONN_REQ_ADVA_OFF (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
@@ -149,16 +145,10 @@ struct ble_ll_conn_stats
uint32_t slave_rxd_bad_conn_req_params;
uint32_t slave_ce_failures;
uint32_t rx_resent_pdus;
- uint32_t data_pdu_rx_valid;
- uint32_t data_pdu_rx_invalid;
- uint32_t data_pdu_rx_bad_llid;
uint32_t data_pdu_rx_dup;
- uint32_t data_pdu_txd;
uint32_t data_pdu_txg;
uint32_t data_pdu_txf;
uint32_t conn_req_txd;
- uint32_t ctrl_pdu_rxd;
- uint32_t l2cap_pdu_rxd;
};
struct ble_ll_conn_stats g_ble_ll_conn_stats;
@@ -573,7 +563,14 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm, int beg_transition)
ble_ll_wfr_enable(wfr_time, ble_ll_conn_wait_txend, connsm);
}
- ++g_ble_ll_conn_stats.data_pdu_txd;
+ /* Increment packets transmitted */
+ if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
+ ++g_ble_ll_stats.tx_ctrl_pdus;
+ g_ble_ll_stats.tx_ctrl_bytes += OS_MBUF_PKTHDR(m)->omp_len;
+ } else {
+ ++g_ble_ll_stats.tx_data_pdus;
+ g_ble_ll_stats.tx_data_bytes += OS_MBUF_PKTHDR(m)->omp_len;
+ }
}
return rc;
@@ -860,13 +857,11 @@ ble_ll_conn_sm_start(struct ble_ll_conn_sm *connsm)
connsm->cons_rxd_bad_crc = 0;
connsm->last_rxd_sn = 1;
- /* XXX: Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets
- exceeds the minimum, data length procedure needs to occur */
/* initialize data length mgmt */
conn_params = &g_ble_ll_conn_params;
connsm->max_tx_octets = conn_params->conn_init_max_tx_octets;
connsm->max_rx_octets = conn_params->supp_max_rx_octets;
- connsm->max_tx_time = conn_params->conn_init_max_tx_octets;
+ connsm->max_tx_time = conn_params->conn_init_max_tx_time;
connsm->max_rx_time = conn_params->supp_max_rx_time;
connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN;
connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN;
@@ -877,7 +872,19 @@ ble_ll_conn_sm_start(struct ble_ll_conn_sm *connsm)
connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
- /* XXX: Controller notifies host of changes to effective tx/rx time/bytes*/
+ /*
+ * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets
+ * exceeds the minimum, data length procedure needs to occur
+ */
+ if ((connsm->max_tx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
+ (connsm->max_rx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
+ (connsm->max_tx_time > BLE_LL_CONN_SUPP_TIME_MIN) ||
+ (connsm->max_rx_time > BLE_LL_CONN_SUPP_TIME_MIN)) {
+ /* Start the data length update procedure */
+ if (ble_ll_read_supp_features() & BLE_LL_FEAT_DATA_LEN_EXT) {
+ ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
+ }
+ }
/* Add to list of active connections */
SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
@@ -916,6 +923,58 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
}
/**
+ * Called when a remotes data length parameters change.
+ *
+ * Context: Link Layer task
+ *
+ * @param connsm
+ * @param req
+ */
+void
+ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm,
+ struct ble_ll_len_req *req)
+{
+ int send_event;
+ uint16_t eff_time;
+ uint16_t eff_bytes;
+
+ /* Update parameters */
+ connsm->rem_max_rx_time = req->max_rx_time;
+ connsm->rem_max_tx_time = req->max_tx_time;
+ connsm->rem_max_rx_octets = req->max_rx_bytes;
+ connsm->rem_max_tx_octets = req->max_tx_bytes;
+
+ /* Assume no event sent */
+ send_event = 0;
+
+ /* See if effective times have changed */
+ eff_time = min(connsm->rem_max_rx_time, connsm->max_rx_time);
+ if (eff_time != connsm->eff_max_rx_time) {
+ connsm->eff_max_rx_time = eff_time;
+ send_event = 1;
+ }
+ eff_time = min(connsm->rem_max_tx_time, connsm->max_tx_time);
+ if (eff_time != connsm->eff_max_tx_time) {
+ connsm->eff_max_tx_time = eff_time;
+ send_event = 1;
+ }
+ eff_bytes = min(connsm->rem_max_rx_octets, connsm->max_rx_octets);
+ if (eff_bytes != connsm->eff_max_rx_octets) {
+ connsm->eff_max_rx_octets = eff_bytes;
+ send_event = 1;
+ }
+ eff_bytes = min(connsm->rem_max_tx_octets, connsm->max_tx_octets);
+ if (eff_bytes != connsm->eff_max_tx_octets) {
+ connsm->eff_max_tx_octets = eff_bytes;
+ send_event = 1;
+ }
+
+ if (send_event) {
+ ble_ll_ctrl_datalen_chg_event(connsm);
+ }
+}
+
+/**
* Called when a connection is terminated
*
* Context: Link Layer task.
@@ -942,7 +1001,7 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
ble_ll_wfr_disable();
/* Stop any control procedures that might be running */
- os_callout_stop(&connsm->ctrl_proc_timer.cf_c);
+ os_callout_stop(&connsm->ctrl_proc_rsp_timer.cf_c);
/* Remove from the active connection list */
SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
@@ -1129,8 +1188,12 @@ ble_ll_conn_event_end(void *arg)
connsm->slave_cur_window_widening = cur_ww;
}
+ /* Log event end */
ble_ll_log(BLE_LL_LOG_ID_CONN_EV_END, 0, 0, connsm->event_cntr);
+ /* See if we need to start any control procedures */
+ ble_ll_ctrl_chk_proc_start(connsm);
+
/* Schedule the next connection event */
ble_ll_conn_sched_set(connsm);
@@ -1225,6 +1288,8 @@ ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
/**
* Process the HCI command to create a connection.
+ *
+ * Context: Link Layer task (HCI command processing)
*
* @param cmdbuf
*
@@ -1658,7 +1723,7 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok)
if (crcok) {
/* Count valid received data pdus */
- ++g_ble_ll_conn_stats.data_pdu_rx_valid;
+ ++g_ble_ll_stats.rx_valid_data_pdus;
/* We better have a connection state machine */
connsm = g_ble_ll_conn_cur_sm;
@@ -1676,7 +1741,7 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok)
/* Check that the LLID is reasonable */
if ((acl_hdr == 0) ||
((acl_hdr == BLE_LL_LLID_DATA_START) && (acl_len == 0))) {
- ++g_ble_ll_conn_stats.data_pdu_rx_bad_llid;
+ ++g_ble_ll_stats.rx_bad_llid;
goto conn_rx_data_pdu_end;
}
@@ -1705,13 +1770,12 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok)
}
if (acl_hdr == BLE_LL_LLID_CTRL) {
- /* XXX: Process control frame! For now just free */
- ++g_ble_ll_conn_stats.ctrl_pdu_rxd;
+ /* Process control frame! For now just free */
+ ++g_ble_ll_stats.rx_ctrl_pdus;
ble_ll_ctrl_rx_pdu(connsm, rxpdu);
} else {
-
/* Count # of data frames */
- ++g_ble_ll_conn_stats.l2cap_pdu_rxd;
+ ++g_ble_ll_stats.rx_l2cap_pdus;
/* NOTE: there should be at least two bytes available */
assert(OS_MBUF_LEADINGSPACE(rxpdu) >= 2);
@@ -1722,8 +1786,10 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok)
htole16(rxbuf, acl_hdr);
htole16(rxbuf + 2, acl_len);
ble_hs_rx_data(rxpdu);
- return;
}
+
+ /* NOTE: we dont free the mbuf since we handed it off! */
+ return;
} else {
++g_ble_ll_conn_stats.data_pdu_rx_dup;
}
@@ -1731,7 +1797,7 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok)
++g_ble_ll_conn_stats.no_conn_sm;
}
} else {
- ++g_ble_ll_conn_stats.data_pdu_rx_invalid;
+ ++g_ble_ll_stats.rx_invalid_data_pdus;
}
/* Free buffer */
@@ -2099,7 +2165,7 @@ ble_ll_conn_init(void)
*/
connsm = &g_ble_ll_conn_sm[0];
for (i = 0; i < BLE_LL_CONN_CFG_MAX_CONNS; ++i) {
- connsm->conn_handle = i;
+ connsm->conn_handle = i + 1;
STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
/* Initialize empty pdu */
@@ -2128,6 +2194,6 @@ ble_ll_conn_init(void)
maxbytes = BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES + BLE_LL_DATA_MAX_OVERHEAD;
conn_params->conn_init_max_tx_time = ble_ll_pdu_tx_time_get(maxbytes);
- conn_params->conn_init_max_tx_octets = BLE_LL_CFG_SUPP_MAX_TX_BYTES;
+ conn_params->conn_init_max_tx_octets = BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c
index 25c77ba..b04a02f 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -26,27 +26,127 @@
/*
* XXX: TODO
* 1) Do I need to keep track of which procedures have already been done?
- * Do I need to worry about repeating procedures?
- * 2) If we fail to get a LL control PDU we will probably need to know that
- * right? Should I keep a procedure state variable? I could save memory
- * by only using the low 4 bits of the current procedure.
- * 3) Probably create my own pool of control pdu's here. Dont need more
+ * Do I need to worry about repeating procedures?
+ * 2) Should we create pool of control pdu's?. Dont need more
* than the # of connections and can probably deal with quite a few less
* if we have lots of connections.
* 4) os_callout_func_init does not really need to be done every time I
* dont think. Do that once per connection when initialized?
* 5) NOTE: some procedures are allowed to run while others are
* running!!! Fix this in the code
- * 6) Make sure we send data length change event to host.
- * 7) We need to start the control procedure for data length change!
- * Deal with this.
* 8) What about procedures that have been completed but try to restart?
- * 9) How do I deal with control procedures that are pending? What happens
- * if we cant get an mbuf? There will be pending control procedures without
- * one running. WHen/how do I deal with that?
- * 10) Make sure that we stop the data length update procedure if we receive
- * a response. Need to look at that.
+ * 12) NOTE: there is a supported features procedure. However, in the case
+ * of data length extension, if the receiving device does not understand
+ * the pdu or it does not support data length extension, the LL_UNKNOWN_RSP
+ * pdu is sent. That needs to be processed...
+ * 14) Will I need to know which procedures actually completed?
+ * 15) We are supposed to remember when we do the data length update proc if
+ * the device sent us an unknown rsp. We should not send it another len req.
+ * Implement this.
+ * 16) Remember: some procedures dont have timeout rules.
+ * 17) remember to stop procedure when rsp received.
+ * 18) Says that we should reset procedure timer whenever a LL control pdu
+ * is queued for transmission. I dont get it... do some procedures send
+ * multiple packets? I guess so.
+ * 19) How to count control pdus sent. DO we count enqueued + sent, or only
+ * sent (actually attempted to tx). Do we count failures? How?
+ *
+ */
+
+/* XXX: Improvements
+ * 1) We can inititalize the procedure timer once per connection state machine
+ */
+
+/* Checks if a particular control procedure is running */
+#define IS_PENDING_CTRL_PROC_M(sm, proc) (sm->pending_ctrl_procs & (1 << proc))
+
+static int
+ble_ll_ctrl_chk_supp_bytes(uint16_t bytes)
+{
+ int rc;
+
+ if ((bytes < BLE_LL_CONN_SUPP_BYTES_MIN) ||
+ (bytes > BLE_LL_CONN_SUPP_BYTES_MAX)) {
+ rc = 0;
+ } else {
+ rc = 1;
+ }
+
+ return rc;
+}
+
+static int
+ble_ll_ctrl_chk_supp_time(uint16_t t)
+{
+ int rc;
+
+ if ((t < BLE_LL_CONN_SUPP_TIME_MIN) || (t > BLE_LL_CONN_SUPP_TIME_MAX)) {
+ rc = 0;
+ } else {
+ rc = 1;
+ }
+
+ return rc;
+}
+
+static int
+ble_ll_ctrl_len_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+ int rc;
+ struct ble_ll_len_req ctrl_req;
+
+ /* Extract parameters and check if valid */
+ ctrl_req.max_rx_bytes = le16toh(dptr + 3);
+ ctrl_req.max_rx_time = le16toh(dptr + 5);
+ ctrl_req.max_tx_bytes = le16toh(dptr + 7);
+ ctrl_req.max_tx_time = le16toh(dptr + 9);
+
+ if (!ble_ll_ctrl_chk_supp_bytes(ctrl_req.max_rx_bytes) ||
+ !ble_ll_ctrl_chk_supp_bytes(ctrl_req.max_tx_bytes) ||
+ !ble_ll_ctrl_chk_supp_time(ctrl_req.max_tx_time) ||
+ !ble_ll_ctrl_chk_supp_time(ctrl_req.max_rx_time)) {
+ rc = 1;
+ } else {
+ /* Update the connection with the new parameters */
+ ble_ll_conn_datalen_update(connsm, &ctrl_req);
+ rc = 0;
+ }
+
+ return rc;
+}
+
+/**
+ * Called to process and UNKNOWN_RSP LL control packet.
+ *
+ * Context: Link Layer Task
+ *
+ * @param dptr
*/
+static void
+ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+ uint8_t ctrl_proc;
+ uint8_t opcode;
+
+ /* Get opcode of unknown LL control frame */
+ opcode = dptr[3];
+
+ /* Convert opcode to control procedure id */
+ switch (opcode) {
+ case BLE_LL_CTRL_LENGTH_REQ:
+ ctrl_proc = BLE_LL_CTRL_PROC_DATA_LEN_UPD;
+ break;
+ default:
+ ctrl_proc = BLE_LL_CTRL_PROC_NUM;
+ break;
+ }
+
+ /* If we are running this one currently, stop it */
+ if (connsm->cur_ctrl_proc == ctrl_proc) {
+ /* Stop the control procedure */
+ ble_ll_ctrl_proc_stop(connsm, ctrl_proc);
+ }
+}
/**
* Send a data length change event for a connection to the host.
@@ -75,6 +175,24 @@ ble_ll_ctrl_datalen_chg_event(struct ble_ll_conn_sm *connsm)
}
/**
+ * Create a link layer length request or length response PDU.
+ *
+ * NOTE: this function does not set the LL data pdu header nor does it
+ * set the opcode in the buffer.
+ *
+ * @param connsm
+ * @param dptr: Pointer to where control pdu payload starts
+ */
+static void
+ble_ll_ctrl_datalen_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+ htole16(dptr + 3, connsm->max_rx_octets);
+ htole16(dptr + 5, connsm->max_rx_time);
+ htole16(dptr + 7, connsm->max_tx_octets);
+ htole16(dptr + 9, connsm->max_tx_time);
+}
+
+/**
* Callback when LL control procedure times out (for a given connection). If
* this is called, it means that we need to end the connection because it
* has not responded to a LL control request.
@@ -84,7 +202,7 @@ ble_ll_ctrl_datalen_chg_event(struct ble_ll_conn_sm *connsm)
* @param arg Pointer to connection state machine.
*/
void
-ble_ll_ctrl_proc_timer_cb(void *arg)
+ble_ll_ctrl_proc_rsp_timer_cb(void *arg)
{
/* Control procedure has timed out. Kill the connection */
ble_ll_conn_end((struct ble_ll_conn_sm *)arg, BLE_ERR_LMP_LL_RSP_TMO);
@@ -115,12 +233,7 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
case BLE_LL_CTRL_PROC_DATA_LEN_UPD:
len = BLE_LL_CTRL_LENGTH_REQ_LEN;
opcode = BLE_LL_CTRL_LENGTH_REQ;
- htole16(dptr + 3, connsm->max_rx_octets);
- htole16(dptr + 5, connsm->max_rx_time);
- htole16(dptr + 7, connsm->max_tx_octets);
- htole16(dptr + 9, connsm->max_tx_time);
- om->om_len = BLE_LL_CTRL_LENGTH_REQ_LEN + BLE_LL_PDU_HDR_LEN;
- OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
+ ble_ll_ctrl_datalen_upd_make(connsm, dptr);
break;
default:
assert(0);
@@ -128,9 +241,12 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
}
/* Set llid, length and opcode */
+ ++len;
dptr[0] = BLE_LL_LLID_CTRL;
dptr[1] = len;
dptr[2] = opcode;
+ om->om_len = len + BLE_LL_PDU_HDR_LEN;
+ OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
}
return om;
@@ -138,6 +254,8 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
/**
* Stops the LL control procedure indicated by 'ctrl_proc'.
+ *
+ * Context: Link Layer task
*
* @param connsm
* @param ctrl_proc
@@ -146,17 +264,21 @@ void
ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc)
{
if (connsm->cur_ctrl_proc == ctrl_proc) {
- os_callout_stop(&connsm->ctrl_proc_timer.cf_c);
+ os_callout_stop(&connsm->ctrl_proc_rsp_timer.cf_c);
connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
connsm->pending_ctrl_procs &= ~(1 << ctrl_proc);
}
- /* XXX: if there are more pending ones, what do we do? */
+
+ /* If there are others, start them */
+ ble_ll_ctrl_chk_proc_start(connsm);
}
/**
* Called to start a LL control procedure. We always set the control
* procedure pending bit even if the input control procedure has been
* initiated.
+ *
+ * Context: Link Layer task.
*
* @param connsm Pointer to connection state machine.
*/
@@ -176,14 +298,14 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
/* Add packet to transmit queue of connection */
ble_ll_conn_enqueue_pkt(connsm, om);
- /* Initialize the host timer */
- os_callout_func_init(&connsm->ctrl_proc_timer,
+ /* Initialize the procedure response timeout */
+ os_callout_func_init(&connsm->ctrl_proc_rsp_timer,
&g_ble_ll_data.ll_evq,
- ble_ll_ctrl_proc_timer_cb,
+ ble_ll_ctrl_proc_rsp_timer_cb,
connsm);
/* Re-start the timer. Control procedure timeout is 40 seconds */
- os_callout_reset(&connsm->ctrl_proc_timer.cf_c,
+ os_callout_reset(&connsm->ctrl_proc_rsp_timer.cf_c,
OS_TICKS_PER_SEC * 40);
}
}
@@ -193,9 +315,37 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
}
/**
- * Called when the Link Layer receives a LL control PDU.
+ * Called to determine if we need to start a LL control procedure for the given
+ * connection.
+ *
+ * Context: Link Layer
*
- * NOTE: the calling function frees the mbuf!
+ * @param connsm Pointer to connection state machine.
+ */
+void
+ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm)
+{
+ int i;
+
+ /* If there is a running procedure or no pending, do nothing */
+ if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) &&
+ (connsm->pending_ctrl_procs != 0)) {
+ /*
+ * The specification says there is no priority to control procedures
+ * so just start from the first one for now.
+ */
+ for (i = 0; i < BLE_LL_CTRL_PROC_NUM; ++i) {
+ if (IS_PENDING_CTRL_PROC_M(connsm, i)) {
+ ble_ll_ctrl_proc_start(connsm, i);
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Called when the Link Layer receives a LL control PDU. This function
+ * must either free the received pdu or re-use it for the response.
*
* Context: Link Layer
*
@@ -205,6 +355,116 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
void
ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
{
- /* XXX: implement */
-}
+ uint8_t features;
+ uint8_t len;
+ uint8_t opcode;
+ uint8_t *dptr;
+
+ /* XXX: where do we validate length received and packet header length?
+ * do this in LL task when received. Someplace!!! What I mean
+ * is we should validate the over the air length with the mbuf length.
+ Should the PHY do that???? */
+
+ /* Get length and opcode from PDU */
+ dptr = om->om_data;
+ len = dptr[1];
+ opcode = dptr[2];
+ /* opcode must be good */
+ if ((opcode > BLE_LL_CTRL_LENGTH_RSP) || (len < 1) ||
+ (len > BLE_LL_CTRL_MAX_PAYLOAD)) {
+ goto rx_malformed_ctrl;
+ }
+
+ /* Subtract the opcode from the length */
+ --len;
+
+ switch (opcode) {
+ case BLE_LL_CTRL_LENGTH_REQ:
+ /* Check length */
+ if (len != BLE_LL_CTRL_LENGTH_REQ_LEN) {
+ goto rx_malformed_ctrl;
+ }
+
+ /* Check parameters for validity */
+ features = ble_ll_read_supp_features();
+ if (features & BLE_LL_FEAT_DATA_LEN_EXT) {
+ /* Extract parameters and check if valid */
+ if (ble_ll_ctrl_len_proc(connsm, dptr)) {
+ goto rx_malformed_ctrl;
+ }
+
+ /*
+ * If we have not started this procedure ourselves and it is
+ * pending, no need to perform it.
+ */
+ if ((connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_DATA_LEN_UPD) &&
+ IS_PENDING_CTRL_PROC_M(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD)) {
+ connsm->pending_ctrl_procs &= ~BLE_LL_CTRL_PROC_DATA_LEN_UPD;
+ }
+
+ /* Send a response */
+ opcode = BLE_LL_CTRL_LENGTH_RSP;
+ ble_ll_ctrl_datalen_upd_make(connsm, dptr);
+ } else {
+ /* XXX: construct unknown pdu */
+ opcode = BLE_LL_CTRL_UNKNOWN_RSP;
+ len = BLE_LL_CTRL_UNK_RSP_LEN;
+ dptr[3] = BLE_LL_CTRL_LENGTH_REQ;
+ }
+ break;
+ case BLE_LL_CTRL_LENGTH_RSP:
+ /* Check length (response length same as request length) */
+ if (len != BLE_LL_CTRL_LENGTH_REQ_LEN) {
+ goto rx_malformed_ctrl;
+ }
+
+ /*
+ * According to specification, we should only process this if we
+ * asked for it.
+ */
+ if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_DATA_LEN_UPD) {
+ /* Process the received data */
+ if (ble_ll_ctrl_len_proc(connsm, dptr)) {
+ goto rx_malformed_ctrl;
+ }
+
+ /* Stop the control procedure */
+ ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
+ }
+ opcode = 255;
+ break;
+ case BLE_LL_CTRL_UNKNOWN_RSP:
+ /* Check length (response length same as request length) */
+ if (len != BLE_LL_CTRL_UNK_RSP_LEN) {
+ goto rx_malformed_ctrl;
+ }
+
+ ble_ll_ctrl_proc_unk_rsp(connsm, dptr);
+ opcode = 255;
+ break;
+ default:
+ /* XXX: this is an un-implemented control procedure. What to do? */
+ opcode = 255;
+ break;
+ }
+
+ /* Free mbuf or send response */
+ if (opcode == 255) {
+ os_mbuf_free(om);
+ } else {
+ ++len;
+ dptr[0] = BLE_LL_LLID_CTRL;
+ dptr[1] = len;
+ dptr[2] = opcode;
+ om->om_len = len + BLE_LL_PDU_HDR_LEN;
+ OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
+ ble_ll_conn_enqueue_pkt(connsm, om);
+ }
+ return;
+
+rx_malformed_ctrl:
+ os_mbuf_free(om);
+ ++g_ble_ll_stats.rx_malformed_ctrl_pdus;
+ return;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/controller/src/ble_ll_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci.c b/net/nimble/controller/src/ble_ll_hci.c
index c162227..9fe7c9e 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -118,6 +118,7 @@ ble_ll_hci_le_read_local_features(uint8_t *rspbuf, uint8_t *rsplen)
{
/* Add list of supported features. */
memset(rspbuf, 0, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN);
+ rspbuf[0] = ble_ll_read_supp_features();
*rsplen = BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN;
return BLE_ERR_SUCCESS;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/net/nimble/host/src/host_dbg.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_dbg.c b/net/nimble/host/src/host_dbg.c
index b71677c..736a719 100644
--- a/net/nimble/host/src/host_dbg.c
+++ b/net/nimble/host/src/host_dbg.c
@@ -77,7 +77,13 @@ host_hci_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
console_printf("LE connection complete. FAIL (status=%u)\n",status);
}
break;
-
+ case BLE_HCI_LE_SUBEV_DATA_LEN_CHG:
+ console_printf("Data Length Change. handle=%u max_tx_bytes=%u "
+ "max_tx_time=%u max_rx_bytes=%u max_rx_time=%u\n",
+ le16toh(evdata), le16toh(evdata + 2),
+ le16toh(evdata + 4), le16toh(evdata + 6),
+ le16toh(evdata + 8));
+ break;
default:
console_printf("\tUnknown LE event\n");
break;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/05254c74/project/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/project/bletest/src/main.c b/project/bletest/src/main.c
index 0dca7b5..6fbe3cd 100755
--- a/project/bletest/src/main.c
+++ b/project/bletest/src/main.c
@@ -62,7 +62,7 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
#define BLETEST_ROLE_ADVERTISER (0)
#define BLETEST_ROLE_SCANNER (1)
#define BLETEST_ROLE_INITIATOR (2)
-#define BLETEST_CFG_ROLE (BLETEST_ROLE_ADVERTISER)
+#define BLETEST_CFG_ROLE (BLETEST_ROLE_INITIATOR)
#define BLETEST_CFG_FILT_DUP_ADV (0)
#define BLETEST_CFG_ADV_ITVL (500000 / BLE_HCI_ADV_ITVL)
#define BLETEST_CFG_ADV_TYPE BLE_HCI_ADV_TYPE_ADV_IND
@@ -267,14 +267,9 @@ bletest_execute(void)
int rc;
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
- /* Enable advertising */
+ /* */
if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
- if (g_bletest_state) {
- rc = host_hci_cmd_le_set_adv_enable(0);
- host_hci_outstanding_opcode = 0;
- assert(rc == 0);
- g_bletest_state = 0;
- } else {
+ if (!g_bletest_state) {
rc = host_hci_cmd_le_set_adv_enable(1);
host_hci_outstanding_opcode = 0;
assert(rc == 0);
@@ -328,6 +323,8 @@ bletest_timer_cb(void *arg)
void
bletest_task_handler(void *arg)
{
+ int rc;
+ uint64_t event_mask;
struct os_event *ev;
struct os_callout_func *cf;
@@ -356,6 +353,12 @@ bletest_task_handler(void *arg)
bletest_init_initiator();
#endif
+ /* Set the event mask we want to display */
+ event_mask = 0x7FF;
+ rc = host_hci_cmd_le_set_event_mask(event_mask);
+ assert(rc == 0);
+ host_hci_outstanding_opcode = 0;
+
/* Init bletest variables */
g_bletest_state = 0;
g_next_os_time = os_time_get();
[2/2] incubator-mynewt-larva git commit: Get additional 32K of RAM on
nrf52. See errata #33 and #34
Posted by we...@apache.org.
Get additional 32K of RAM on nrf52. See errata #33 and #34
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/acbd147d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/acbd147d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/acbd147d
Branch: refs/heads/master
Commit: acbd147dae0fe9f0ac90b81160042b002094ad6b
Parents: 1d324a7
Author: wes3 <wi...@micosa.io>
Authored: Wed Dec 9 11:09:54 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Wed Dec 9 16:56:56 2015 -0800
----------------------------------------------------------------------
hw/bsp/nrf52pdk/nrf52pdk.ld | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/acbd147d/hw/bsp/nrf52pdk/nrf52pdk.ld
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52pdk/nrf52pdk.ld b/hw/bsp/nrf52pdk/nrf52pdk.ld
index 8be5b6a..144ea23 100755
--- a/hw/bsp/nrf52pdk/nrf52pdk.ld
+++ b/hw/bsp/nrf52pdk/nrf52pdk.ld
@@ -33,10 +33,17 @@
*/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
+/*
+ * NOTE: This linker script is for version 1.0 of the nrf52. See
+ * errata #33 and #34 on nordic infocenter website for details. This errata
+ * causes us to allocate a memory regision we call "CODE_RAM" so that we can
+ * access the full 64K RAM provided by the chip.
+ */
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
- RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x8000
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x8000
+ CODE_RAM (rwx) : ORIGIN = 0x8000000, LENGTH = 0x8000
}
/* Linker script to place sections and symbol values. Should be used together
@@ -168,20 +175,20 @@ SECTIONS
__bss_end__ = .;
} > RAM
- /* Heap starts after BSS */
- __HeapBase = .;
-
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
*(.stack*)
- } > RAM
-
- /* Set stack top to end of RAM, and stack limit move down by
- * size of stack_dummy section */
- __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ } > CODE_RAM
+
+ /*
+ * Place heap and stack in CODE_RAM. Heap is at start, stack is at the
+ * top and stack limit is the bottom of the stack.
+ */
+ __HeapBase = ORIGIN(CODE_RAM);
+ __StackTop = ORIGIN(CODE_RAM) + LENGTH(CODE_RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);