53 #include "rf_data_entry.h" 55 #include "rf_ble_cmd.h" 56 #include "lib/random.h" 60 #include "inc/hw_types.h" 61 #include "inc/hw_rfc_dbell.h" 68 #define LOG_MODULE "BLE-RADIO" 69 #define LOG_LEVEL LOG_LEVEL_MAIN 71 #define CMD_GET_STATUS(X) (((rfc_radioOp_t *)X)->status) 72 #define RX_ENTRY_STATUS(X) (((rfc_dataEntry_t *)X)->status) 73 #define RX_ENTRY_LENGTH(X) (((rfc_dataEntry_t *)X)->length) 74 #define RX_ENTRY_TYPE(X) (((rfc_dataEntry_t *)X)->config.type) 75 #define RX_ENTRY_NEXT_ENTRY(X) (((rfc_dataEntry_t *)X)->pNextEntry) 76 #define RX_ENTRY_DATA_LENGTH(X) ((X)[8]) 77 #define RX_ENTRY_DATA_PTR(X) (&(X)[9]) 78 #define TX_ENTRY_STATUS(X) RX_ENTRY_STATUS(X) 79 #define TX_ENTRY_LENGTH(X) RX_ENTRY_LENGTH(X) 80 #define TX_ENTRY_TYPE(X) RX_ENTRY_TYPE(X) 81 #define TX_ENTRY_NEXT_ENTRY(X) RX_ENTRY_NEXT_ENTRY(X) 82 #define TX_ENTRY_FRAME_TYPE(X) ((X)[8]) 83 #define TX_ENTRY_DATA_PTR(X) (&(X)[9]) 91 return LPM_MODE_SLEEP;
94 return LPM_MODE_MAX_SUPPORTED;
97 LPM_MODULE(cc26xx_ble_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
100 #define TIME_UNIT_MS 1000 101 #define TIME_UNIT_0_625_MS 1600 102 #define TIME_UNIT_1_25_MS 800 103 #define TIME_UNIT_10_MS 100 104 #define TIME_UNIT_RF_CORE 4000000 105 #define TIME_UNIT_RTIMER RTIMER_SECOND 108 ticks_from_unit(uint32_t value, uint32_t unit)
110 double temp = (((double)value) / unit) * RTIMER_SECOND;
111 return (rtimer_clock_t)temp;
114 ticks_to_unit(rtimer_clock_t value, uint32_t unit)
116 double temp = (((double)value) / RTIMER_SECOND) * unit;
117 return (uint32_t)temp;
120 #define CMD_BUFFER_SIZE 24 121 #define PARAM_BUFFER_SIZE 36 122 #define OUTPUT_BUFFER_SIZE 24 125 #define ADV_RX_BUFFERS_OVERHEAD 8 126 #define ADV_RX_BUFFERS_DATA_LEN 60 127 #define ADV_RX_BUFFERS_LEN (ADV_RX_BUFFERS_OVERHEAD + ADV_RX_BUFFERS_DATA_LEN) 128 #define ADV_RX_BUFFERS_NUM 2 130 #define ADV_PREPROCESSING_TIME_TICKS 65 134 uint16_t adv_interval;
135 ble_adv_type_t adv_type;
136 ble_addr_type_t own_addr_type;
138 uint8_t adv_data_len;
139 uint8_t adv_data[BLE_ADV_DATA_LEN];
140 uint8_t scan_rsp_data_len;
141 uint8_t scan_rsp_data[BLE_ADV_DATA_LEN];
144 rtimer_clock_t start_rt;
147 uint8_t cmd_buf[CMD_BUFFER_SIZE];
148 uint8_t param_buf[PARAM_BUFFER_SIZE];
149 uint8_t output_buf[OUTPUT_BUFFER_SIZE];
150 dataQueue_t rx_queue;
151 uint8_t rx_buffers[ADV_RX_BUFFERS_NUM][ADV_RX_BUFFERS_LEN];
152 uint8_t *rx_queue_current;
155 static ble_adv_param_t adv_param;
156 static void advertising_event(
struct rtimer *t,
void *ptr);
159 #define BLE_MODE_MAX_CONNECTIONS 1 162 #ifdef BLE_MODE_CONF_CONN_MAX_PACKET_SIZE 163 #define BLE_MODE_CONN_MAX_PACKET_SIZE BLE_MODE_CONF_CONN_MAX_PACKET_SIZE 165 #define BLE_MODE_CONN_MAX_PACKET_SIZE 256 168 #define CONN_BLE_BUFFER_SIZE 27 170 #define CONN_RX_BUFFERS_OVERHEAD 8 171 #define CONN_RX_BUFFERS_DATA_LEN 60 172 #define CONN_RX_BUFFERS_LEN (CONN_RX_BUFFERS_OVERHEAD + CONN_RX_BUFFERS_DATA_LEN) 173 #define CONN_RX_BUFFERS_NUM 12 176 #define DATA_ENTRY_FREE 5 177 #define DATA_ENTRY_QUEUED 6 179 #define CONN_TX_BUFFERS_OVERHEAD 9 180 #define CONN_TX_BUFFERS_DATA_LEN 27 181 #define CONN_TX_BUFFERS_LEN (CONN_TX_BUFFERS_OVERHEAD + CONN_TX_BUFFERS_DATA_LEN) 182 #define CONN_TX_BUFFERS_NUM 12 184 #define CONN_WIN_SIZE 1 185 #define CONN_WIN_OFFSET 20 187 #define CONN_EVENT_LATENCY_THRESHOLD 10 188 #define CONN_WINDOW_WIDENING_TICKS 30 189 #define CONN_PREPROCESSING_TIME_TICKS 100 191 #define CONN_UPDATE_DELAY 6 195 uint8_t peer_address[BLE_ADDR_SIZE];
196 uint32_t access_address;
205 uint64_t channel_map;
206 uint8_t num_used_channels;
209 rtimer_clock_t timestamp_rt;
213 uint8_t unmapped_channel;
214 uint8_t mapped_channel;
215 rtimer_clock_t start_rt;
216 uint16_t conn_handle;
219 uint8_t cmd_buf[CMD_BUFFER_SIZE];
220 uint8_t param_buf[PARAM_BUFFER_SIZE];
221 uint8_t output_buf[OUTPUT_BUFFER_SIZE];
222 dataQueue_t rx_queue;
223 uint8_t rx_buffers[CONN_RX_BUFFERS_NUM][CONN_RX_BUFFERS_LEN];
224 uint8_t *rx_queue_current;
225 dataQueue_t tx_queue;
226 uint8_t tx_buffers[CONN_TX_BUFFERS_NUM][CONN_TX_BUFFERS_LEN];
227 uint8_t tx_buffers_sent;
228 uint16_t skipped_events;
230 uint64_t channel_update_channel_map;
231 uint16_t channel_update_counter;
232 uint8_t channel_update_num_used_channels;
234 uint8_t conn_update_win_size;
235 uint16_t conn_update_win_offset;
236 uint16_t conn_update_interval;
237 uint16_t conn_update_latency;
238 uint16_t conn_update_timeout;
239 uint16_t conn_update_counter;
242 static ble_conn_param_t conn_param[BLE_MODE_MAX_CONNECTIONS];
244 static uint16_t conn_counter = 0;
246 static void connection_event_slave(
struct rtimer *t,
void *ptr);
248 PROCESS(ble_hal_conn_rx_process,
"BLE/CC26xx connection RX process");
249 process_event_t rx_data_event;
255 ble_conn_param_t *conn;
257 rfc_dataEntry_t *entry;
260 memset(&adv_param, 0x00,
sizeof(ble_adv_param_t));
261 memset(&adv_param.rx_queue, 0x00,
sizeof(adv_param.rx_queue));
262 adv_param.rx_queue.pCurrEntry = adv_param.rx_buffers[0];
263 adv_param.rx_queue.pLastEntry = NULL;
264 adv_param.rx_queue_current = adv_param.rx_buffers[0];
265 for(i = 0; i < ADV_RX_BUFFERS_NUM; i++) {
266 memset(&adv_param.rx_buffers[i], 0x00, ADV_RX_BUFFERS_LEN);
267 entry = (rfc_dataEntry_t *)adv_param.rx_buffers[i];
268 entry->pNextEntry = adv_param.rx_buffers[(i + 1) % ADV_RX_BUFFERS_NUM];
269 entry->config.lenSz = 1;
270 entry->length = ADV_RX_BUFFERS_DATA_LEN;
273 memset(conn_param, 0x00,
sizeof(ble_conn_param_t) * BLE_MODE_MAX_CONNECTIONS);
274 for(conn_count = 0; conn_count < BLE_MODE_MAX_CONNECTIONS; conn_count++) {
276 conn = &conn_param[conn_count];
277 memset(&conn->rx_queue, 0x00,
sizeof(conn->rx_queue));
278 conn->rx_queue.pCurrEntry = conn->rx_buffers[0];
279 conn->rx_queue.pLastEntry = NULL;
280 conn->rx_queue_current = conn->rx_buffers[0];
282 for(i = 0; i < CONN_RX_BUFFERS_NUM; i++) {
283 memset(&conn->rx_buffers[i], 0x00, CONN_RX_BUFFERS_LEN);
284 entry = (rfc_dataEntry_t *)conn->rx_buffers[i];
285 entry->pNextEntry = conn->rx_buffers[(i + 1) % CONN_RX_BUFFERS_NUM];
286 entry->config.lenSz = 1;
287 entry->length = CONN_RX_BUFFERS_DATA_LEN;
291 memset(&conn->tx_queue, 0x00,
sizeof(conn->tx_queue));
292 conn->tx_queue.pCurrEntry = NULL;
293 conn->tx_queue.pLastEntry = NULL;
295 for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) {
296 memset(&conn->tx_buffers[i], 0x00, CONN_TX_BUFFERS_LEN);
297 entry = (rfc_dataEntry_t *)conn->tx_buffers[i];
298 entry->config.lenSz = 1;
299 entry->status = DATA_ENTRY_FREE;
304 static ble_conn_param_t *
305 get_connection_for_handle(uint8_t conn_handle)
308 for(i = 0; i < BLE_MODE_MAX_CONNECTIONS; i++) {
309 if(conn_param[i].conn_handle == conn_handle) {
310 return &conn_param[i];
317 tx_queue_get_buffer(ble_conn_param_t *param)
320 rfc_dataEntry_t *entry;
321 for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) {
322 entry = (rfc_dataEntry_t *)param->tx_buffers[i];
323 if(entry->status == DATA_ENTRY_FREE) {
324 return (uint8_t *)entry;
331 tx_queue_count_free_buffers(ble_conn_param_t *param)
334 uint16_t free_bufs = 0;
335 for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) {
336 if(TX_ENTRY_STATUS(param->tx_buffers[i]) == DATA_ENTRY_FREE) {
344 tx_queue_data_to_transmit(ble_conn_param_t *param)
347 for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) {
348 if(TX_ENTRY_STATUS(param->tx_buffers[i]) == DATA_ENTRY_QUEUED) {
362 LOG_ERR(
"ble_controller_reset() could not boot rf-core\n");
363 return BLE_RESULT_ERROR;
370 LOG_ERR(
"could not setup rf-core to BLE mode\n");
371 return BLE_RESULT_ERROR;
374 return BLE_RESULT_OK;
387 LOG_INFO(
"maximum connections: %4d\n", BLE_MODE_MAX_CONNECTIONS);
388 LOG_INFO(
"max. packet length: %4d\n", BLE_MODE_CONN_MAX_PACKET_SIZE);
392 if(
on() != BLE_RESULT_OK) {
393 return BLE_RESULT_ERROR;
400 return BLE_RESULT_OK;
404 read_bd_addr(uint8_t *
addr)
407 return BLE_RESULT_OK;
411 read_buffer_size(
unsigned int *buf_len,
unsigned int *num_buf)
414 uint16_t ll_buffers = CONN_TX_BUFFERS_NUM;
415 uint16_t packet_buffers;
416 uint16_t buffer_size;
417 for(i = 0; i < conn_counter; i++) {
418 ll_buffers = MIN(ll_buffers, tx_queue_count_free_buffers(&conn_param[i]));
420 packet_buffers = ll_buffers / (BLE_MODE_CONN_MAX_PACKET_SIZE / CONN_BLE_BUFFER_SIZE);
421 buffer_size = BLE_MODE_CONN_MAX_PACKET_SIZE;
422 memcpy(buf_len, &buffer_size, 2);
423 memcpy(num_buf, &packet_buffers, 2);
424 return BLE_RESULT_OK;
428 set_adv_param(
unsigned int adv_int, ble_adv_type_t type,
429 ble_addr_type_t own_type,
unsigned short adv_map)
431 adv_param.adv_interval = adv_int;
432 adv_param.adv_type = type;
433 adv_param.own_addr_type = own_type;
434 adv_param.channel_map = adv_map;
436 LOG_INFO(
"advertising parameter: interval: %4d, channels: %2d\n",
437 adv_param.adv_interval, adv_param.channel_map);
439 LOG_DBG(
"interval: %16u (ms)\n", adv_param.adv_interval);
440 LOG_DBG(
"type: %16u\n", adv_param.adv_type);
441 LOG_DBG(
"addr_type:%16u\n", adv_param.own_addr_type);
442 LOG_DBG(
"channels: %16u\n", adv_param.channel_map);
444 return BLE_RESULT_OK;
448 read_adv_channel_tx_power(
short *power)
450 return BLE_RESULT_NOT_SUPPORTED;
454 set_adv_data(
unsigned short data_len,
char *data)
456 if(data_len > BLE_ADV_DATA_LEN) {
457 LOG_WARN(
"BLE-HAL: adv_data too long\n");
458 return BLE_RESULT_INVALID_PARAM;
460 adv_param.adv_data_len = data_len;
461 memcpy(adv_param.adv_data, data, data_len);
462 return BLE_RESULT_OK;
466 set_scan_resp_data(
unsigned short data_len,
char *data)
468 if(data_len > BLE_SCAN_RESP_DATA_LEN) {
469 LOG_WARN(
"BLE-HAL: scan_resp_data too long\n");
470 return BLE_RESULT_INVALID_PARAM;
472 adv_param.scan_rsp_data_len = data_len;
473 memcpy(adv_param.scan_rsp_data, data, data_len);
474 return BLE_RESULT_OK;
478 set_adv_enable(
unsigned short enable)
481 if((enable) && (!adv_param.active)) {
482 adv_param.start_rt = now + ticks_from_unit(adv_param.adv_interval,
484 rtimer_set(&adv_param.timer, adv_param.start_rt,
485 0, advertising_event, (
void *)&adv_param);
487 return BLE_RESULT_OK;
491 send_frame(ble_conn_param_t *conn, uint8_t *data, uint8_t data_len, uint8_t frame_type)
493 uint8_t *tx_buffer = tx_queue_get_buffer(conn);
494 if(tx_buffer == NULL) {
495 LOG_WARN(
"BLE-HAL: send_frame: no TX buffer available (conn_handle: 0x%04X)\n", conn->conn_handle);
496 return BLE_RESULT_ERROR;
498 if(data_len > CONN_BLE_BUFFER_SIZE) {
499 LOG_WARN(
"BLE-HAL: send_frame: data too long (%d bytes)\n", data_len);
500 return BLE_RESULT_ERROR;
503 memcpy(TX_ENTRY_DATA_PTR(tx_buffer), data, data_len);
504 TX_ENTRY_LENGTH(tx_buffer) = data_len + 1;
505 TX_ENTRY_STATUS(tx_buffer) = DATA_ENTRY_QUEUED;
506 TX_ENTRY_FRAME_TYPE(tx_buffer) = frame_type;
507 return BLE_RESULT_OK;
511 connection_update(
unsigned int connection_handle,
unsigned int conn_interval,
512 unsigned int conn_latency,
unsigned int supervision_timeout)
516 ble_conn_param_t *conn = get_connection_for_handle(connection_handle);
519 return BLE_RESULT_ERROR;
522 LOG_INFO(
"connection_update: handle: 0x%04X, interval: %4d, latency: %2d, timeout: %4d\n",
523 connection_handle, conn_interval, conn_latency, supervision_timeout);
525 uint16_t instant = conn->counter + CONN_UPDATE_DELAY;
527 data[0] = BLE_LL_CONN_UPDATE_REQ;
528 data[1] = conn->win_size;
531 memcpy(&data[4], &conn_interval, 2);
532 memcpy(&data[6], &conn_latency, 2);
533 memcpy(&data[8], &supervision_timeout, 2);
534 memcpy(&data[10], &instant, 2);
537 conn->conn_update_win_size = conn->win_size;
538 conn->conn_update_interval = conn_interval;
539 conn->conn_update_latency = conn_latency;
540 conn->conn_update_timeout = supervision_timeout;
541 conn->conn_update_counter = instant;
543 if(send_frame(conn, data, len, BLE_DATA_PDU_LLID_CONTROL) != BLE_RESULT_OK) {
544 LOG_ERR(
"connection_update: send frame was NOT successful\n");
545 return BLE_RESULT_ERROR;
548 data[0] = BLE_LL_CONN_PARAM_REQ;
549 memcpy(&data[1], &conn_interval, 2);
550 memcpy(&data[3], &conn_interval, 2);
551 memcpy(&data[5], &conn_latency, 2);
552 memcpy(&data[7], &supervision_timeout, 2);
553 memcpy(&data[9], &conn_interval, 1);
554 memcpy(&data[10], &conn->counter, 2);
555 memset(&data[12], 0xFF, 12);
558 if(send_frame(conn, data, len, BLE_DATA_PDU_LLID_CONTROL) != BLE_RESULT_OK) {
559 LOG_ERR(
"connection_update: send frame was NOT successful\n");
560 return BLE_RESULT_ERROR;
563 return BLE_RESULT_OK;
567 send(
void *buf,
unsigned short buf_len)
571 ble_conn_param_t *conn;
574 linkaddr_t dest_addr;
575 linkaddr_t conn_addr;
578 linkaddr_copy(&dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
580 LOG_DBG(
"ble-hal: sending %d bytes\n", buf_len);
582 for(loop_conn = 0; loop_conn < conn_counter; loop_conn++) {
583 conn = &conn_param[loop_conn];
586 for(loop_data = 0; loop_data < buf_len; loop_data += CONN_BLE_BUFFER_SIZE) {
587 data = &((uint8_t *)buf)[loop_data];
588 data_len = MIN((buf_len - loop_data), CONN_BLE_BUFFER_SIZE);
590 result = send_frame(conn, data, data_len, BLE_DATA_PDU_LLID_DATA_MESSAGE);
592 result = send_frame(conn, data, data_len, BLE_DATA_PDU_LLID_DATA_FRAGMENT);
594 if(result != BLE_RESULT_OK) {
595 LOG_WARN(
"ble-hal: send was unsuccessful\n");
601 return BLE_RESULT_OK;
605 read_connection_interval(
unsigned int conn_handle,
unsigned int *conn_interval)
607 ble_conn_param_t *conn = get_connection_for_handle(conn_handle);
609 memset(conn_interval, 0x00,
sizeof(uint16_t));
610 return BLE_RESULT_ERROR;
612 memcpy(conn_interval, &conn->interval,
sizeof(uint16_t));
613 return BLE_RESULT_OK;
634 read_connection_interval
638 advertising_rx(ble_adv_param_t *param)
643 ble_conn_param_t *c_param = &conn_param[0];
644 rtimer_clock_t wakeup;
646 while(RX_ENTRY_STATUS(param->rx_queue_current) == DATA_ENTRY_FINISHED) {
647 rx_data = RX_ENTRY_DATA_PTR(param->rx_queue_current);
649 if(CMD_GET_STATUS(param->cmd_buf) == RF_CORE_RADIO_OP_STATUS_BLE_DONE_CONNECT) {
651 for(i = 0; i < BLE_ADDR_SIZE; i++) {
652 c_param->peer_address[i] = rx_data[BLE_ADDR_SIZE + 1 - i];
654 memcpy(&c_param->access_address, &rx_data[offset], 4);
655 memcpy(&c_param->crc_init_0, &rx_data[offset + 4], 1);
656 memcpy(&c_param->crc_init_1, &rx_data[offset + 5], 1);
657 memcpy(&c_param->crc_init_2, &rx_data[offset + 6], 1);
658 memcpy(&c_param->win_size, &rx_data[offset + 7], 1);
659 memcpy(&c_param->win_offset, &rx_data[offset + 8], 2);
660 memcpy(&c_param->interval, &rx_data[offset + 10], 2);
661 memcpy(&c_param->latency, &rx_data[offset + 12], 2);
662 memcpy(&c_param->timeout, &rx_data[offset + 14], 2);
663 memcpy(&c_param->channel_map, &rx_data[offset + 16], 5);
664 memcpy(&c_param->hop, &rx_data[offset + 21], 1);
665 memcpy(&c_param->sca, &rx_data[offset + 21], 1);
666 memcpy(&c_param->timestamp_rt, &rx_data[offset + 24], 4);
670 c_param->timestamp_rt = ticks_from_unit(c_param->timestamp_rt, TIME_UNIT_RF_CORE);
671 c_param->hop = c_param->hop & 0x1F;
672 c_param->sca = (c_param->sca >> 5) & 0x07;
674 LOG_INFO(
"connection created: conn_int: %4u, latency: %3u, channel_map: %8llX\n",
675 c_param->interval, c_param->latency, c_param->channel_map);
677 LOG_DBG(
"access address: 0x%08lX\n", c_param->access_address);
678 LOG_DBG(
"crc0: 0x%02X\n", c_param->crc_init_0);
679 LOG_DBG(
"crc1: 0x%02X\n", c_param->crc_init_1);
680 LOG_DBG(
"crc2: 0x%02X\n", c_param->crc_init_2);
681 LOG_DBG(
"win_size: %4u\n", c_param->win_size);
682 LOG_DBG(
"win_offset: %4u\n", c_param->win_offset);
683 LOG_DBG(
"interval: %4u\n", c_param->interval);
684 LOG_DBG(
"latency: %4u\n", c_param->latency);
685 LOG_DBG(
"timeout: %4u\n", c_param->timeout);
686 LOG_DBG(
"channel_map: %llX\n", c_param->channel_map);
690 wakeup = c_param->timestamp_rt + ticks_from_unit(c_param->win_offset, TIME_UNIT_1_25_MS) - CONN_WINDOW_WIDENING_TICKS;
691 wakeup += ticks_from_unit(c_param->interval, TIME_UNIT_1_25_MS) - CONN_PREPROCESSING_TIME_TICKS;
692 rtimer_set(&c_param->timer, wakeup, 0, connection_event_slave, (
void *)c_param);
695 c_param->counter = 0;
696 c_param->unmapped_channel = 0;
697 c_param->conn_handle = conn_counter;
700 LOG_INFO(
"BLE-HAL: connection (0x%04X) created\n", c_param->conn_handle);
704 RX_ENTRY_DATA_LENGTH(param->rx_queue_current) = 0;
705 RX_ENTRY_STATUS(param->rx_queue_current) = DATA_ENTRY_PENDING;
706 param->rx_queue_current = RX_ENTRY_NEXT_ENTRY(param->rx_queue_current);
711 advertising_event(
struct rtimer *t,
void *ptr)
713 ble_adv_param_t *param = (ble_adv_param_t *)ptr;
716 if(
on() != BLE_RESULT_OK) {
717 LOG_ERR(
"BLE-HAL: advertising event: could not enable rf core\n");
722 param->adv_data_len, param->adv_data,
723 param->scan_rsp_data_len, param->scan_rsp_data,
724 param->own_addr_type, (uint8_t *)BLE_ADDR_LOCATION);
727 if(param->channel_map & BLE_ADV_CHANNEL_1_MASK) {
729 param->param_buf, param->output_buf);
735 advertising_rx(param);
737 if(conn_param[0].active == 1) {
738 LOG_INFO(
"stop advertising\n");
742 param->start_rt = param->start_rt + ticks_from_unit(param->adv_interval, TIME_UNIT_MS);
743 wakeup = adv_param.start_rt - ADV_PREPROCESSING_TIME_TICKS;
744 rtimer_set(¶m->timer, wakeup, 0, advertising_event, (
void *)param);
748 update_data_channel(ble_conn_param_t *param)
756 param->unmapped_channel = (param->unmapped_channel + param->hop) % (BLE_DATA_CHANNEL_MAX + 1);
759 if(param->channel_map & (1ULL << param->unmapped_channel)) {
761 param->mapped_channel = param->unmapped_channel;
763 remap_index = param->unmapped_channel % param->num_used_channels;
765 for(i = 0; i < (BLE_DATA_CHANNEL_MAX + 1); i++) {
766 if(param->channel_map & (1ULL << i)) {
767 if(j == remap_index) {
768 param->mapped_channel = i;
777 process_ll_ctrl_msg(ble_conn_param_t *conn, uint8_t input_len, uint8_t *
input, uint8_t *output_len, uint8_t *
output)
779 uint8_t op_code = input[0];
783 uint64_t channel_map = 0;
784 uint16_t instant = 0;
787 if(op_code == BLE_LL_CONN_UPDATE_REQ) {
788 LOG_INFO(
"BLE-HAL: connection update request received\n");
789 memcpy(&conn->conn_update_win_size, &input[1], 1);
790 memcpy(&conn->conn_update_win_offset, &input[2], 2);
791 memcpy(&conn->conn_update_interval, &input[4], 2);
792 memcpy(&conn->conn_update_latency, &input[6], 2);
793 memcpy(&conn->conn_update_timeout, &input[8], 2);
794 memcpy(&conn->conn_update_counter, &input[10], 2);
795 }
else if(op_code == BLE_LL_CHANNEL_MAP_REQ) {
796 LOG_INFO(
"BLE-HAL: channel map update received\n");
797 memcpy(&channel_map, &input[1], 5);
798 memcpy(&instant, &input[6], 2);
800 conn->channel_update_channel_map = channel_map;
801 conn->channel_update_counter = instant;
802 conn->channel_update_num_used_channels = 0;
803 for(i = 0; i <= BLE_DATA_CHANNEL_MAX; i++) {
804 if(channel_map & (1ULL << i)) {
805 conn->channel_update_num_used_channels++;
808 }
else if(op_code == BLE_LL_FEATURE_REQ) {
809 LOG_INFO(
"BLE-HAL: feature request received\n");
810 output[0] = BLE_LL_FEATURE_RSP;
811 memset(&output[1], 0x00, 8);
813 }
else if(op_code == BLE_LL_VERSION_IND) {
814 LOG_INFO(
"BLE-HAL: version request received\n");
815 output[0] = BLE_LL_VERSION_IND;
817 memset(&output[2], 0xAA, 4);
819 }
else if(op_code == BLE_LL_CONN_PARAM_REQ) {
820 LOG_INFO(
"BLE-HAL: connection parameter request received\n");
821 memcpy(&interval, &input[1], 2);
822 memcpy(&latency, &input[5], 2);
823 memcpy(&timeout, &input[7], 2);
826 LOG_WARN(
"BLE-HAL: unknown LL control code: %02X\n", op_code);
831 connection_rx(ble_conn_param_t *param)
833 uint8_t header_offset = 2;
840 linkaddr_t sender_addr;
841 rfc_bleMasterSlaveOutput_t *out_buf = (rfc_bleMasterSlaveOutput_t *)param->output_buf;
843 uint8_t output_len = 0;
846 while(RX_ENTRY_STATUS(param->rx_queue_current) == DATA_ENTRY_FINISHED) {
847 rx_data = RX_ENTRY_DATA_PTR(param->rx_queue_current);
848 len = RX_ENTRY_DATA_LENGTH(param->rx_queue_current) - 6 - 2;
849 channel = (rx_data[len + 3] & 0x3F);
850 frame_type = rx_data[0] & 0x03;
851 more_data = (rx_data[0] & 0x10) >> 4;
853 if(frame_type == BLE_DATA_PDU_LLID_CONTROL) {
854 process_ll_ctrl_msg(param, (len - header_offset), &rx_data[header_offset], &output_len, output);
856 send_frame(param, output, output_len, BLE_DATA_PDU_LLID_CONTROL);
858 }
else if(frame_type == BLE_DATA_PDU_LLID_DATA_MESSAGE) {
862 rssi = out_buf->lastRssi;
864 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
865 packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, channel);
867 packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &sender_addr);
868 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME_BLE_RX_EVENT);
869 if((!more_data) || (len < CONN_BLE_BUFFER_SIZE)) {
870 NETSTACK_MAC.
input();
872 }
else if(frame_type == BLE_DATA_PDU_LLID_DATA_FRAGMENT) {
875 if((!more_data) || (len < CONN_BLE_BUFFER_SIZE)) {
876 NETSTACK_MAC.
input();
881 RX_ENTRY_DATA_LENGTH(param->rx_queue_current) = 0;
882 RX_ENTRY_STATUS(param->rx_queue_current) = DATA_ENTRY_PENDING;
883 param->rx_queue_current = RX_ENTRY_NEXT_ENTRY(param->rx_queue_current);
888 connection_event_slave(
struct rtimer *t,
void *ptr)
891 ble_conn_param_t *conn = (ble_conn_param_t *)ptr;
892 rfc_bleMasterSlaveOutput_t *output = (rfc_bleMasterSlaveOutput_t *)conn->output_buf;
893 uint8_t first_packet = 0;
894 rtimer_clock_t wakeup;
896 uint8_t tx_data = tx_queue_data_to_transmit(conn);
898 if(conn->counter == 0) {
900 conn->start_rt = conn->timestamp_rt + ticks_from_unit(conn->win_offset, TIME_UNIT_1_25_MS) - CONN_WINDOW_WIDENING_TICKS;
901 update_data_channel(conn);
907 if(conn->counter == conn->conn_update_counter) {
908 conn->start_rt += ticks_from_unit(conn->interval + conn->conn_update_win_offset, TIME_UNIT_1_25_MS);
910 conn->win_size = conn->conn_update_win_size;
911 conn->win_offset = conn->conn_update_win_offset;
912 conn->interval = conn->conn_update_interval;
913 conn->latency = conn->conn_update_latency;
914 conn->timeout = conn->conn_update_timeout;
915 conn->conn_update_win_size = 0;
916 conn->conn_update_win_offset = 0;
917 conn->conn_update_interval = 0;
918 conn->conn_update_latency = 0;
919 conn->conn_update_timeout = 0;
920 }
else if(output->pktStatus.bTimeStampValid) {
921 conn->start_rt = ticks_from_unit(output->timeStamp, TIME_UNIT_RF_CORE) +
922 ticks_from_unit(conn->interval, TIME_UNIT_1_25_MS) - CONN_WINDOW_WIDENING_TICKS;
924 conn->start_rt += ticks_from_unit(conn->interval, TIME_UNIT_1_25_MS);
928 if(conn->channel_update_counter == conn->counter) {
929 conn->channel_map = conn->channel_update_channel_map;
930 conn->num_used_channels = conn->channel_update_num_used_channels;
931 conn->channel_update_counter = 0;
932 conn->channel_update_channel_map = 0;
933 conn->channel_update_num_used_channels = 0;
935 update_data_channel(conn);
937 if(tx_data || (conn->skipped_events >= conn->latency) || (conn->counter < CONN_EVENT_LATENCY_THRESHOLD)) {
939 conn->skipped_events = 0;
941 conn->crc_init_0, conn->crc_init_1, conn->crc_init_2,
942 ticks_to_unit(ticks_from_unit(conn->win_size, TIME_UNIT_1_25_MS), TIME_UNIT_RF_CORE),
943 ticks_to_unit(CONN_WINDOW_WIDENING_TICKS, TIME_UNIT_RF_CORE), first_packet);
946 ticks_to_unit(conn->start_rt, TIME_UNIT_RF_CORE));
948 if(
on() != BLE_RESULT_OK) {
949 LOG_ERR(
"connection_event: could not enable radio core\n");
954 for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) {
955 if(TX_ENTRY_STATUS(conn->tx_buffers[i]) == DATA_ENTRY_QUEUED) {
956 TX_ENTRY_STATUS(conn->tx_buffers[i]) = DATA_ENTRY_PENDING;
964 if(CMD_GET_STATUS(conn->cmd_buf) != RF_CORE_RADIO_OP_STATUS_BLE_DONE_OK) {
965 LOG_DBG(
"command status: 0x%04X; connection event counter: %d, channel: %d\n",
966 CMD_GET_STATUS(conn->cmd_buf), conn->counter, conn->mapped_channel);
970 for(i = 0; i < CONN_TX_BUFFERS_NUM; i++) {
971 if(TX_ENTRY_STATUS(conn->tx_buffers[i]) == DATA_ENTRY_FINISHED) {
972 TX_ENTRY_STATUS(conn->tx_buffers[i]) = DATA_ENTRY_FREE;
973 TX_ENTRY_LENGTH(conn->tx_buffers[i]) = 0;
974 TX_ENTRY_NEXT_ENTRY(conn->tx_buffers[i]) = NULL;
979 conn->skipped_events++;
980 output->pktStatus.bTimeStampValid = 0;
982 wakeup = conn->start_rt + ticks_from_unit(conn->interval, TIME_UNIT_1_25_MS) - CONN_PREPROCESSING_TIME_TICKS;
983 rtimer_set(&conn->timer, wakeup, 0, connection_event_slave, ptr);
984 process_post(&ble_hal_conn_rx_process, rx_data_event, ptr);
988 ble_conn_param_t *conn = (ble_conn_param_t *)data;
989 rfc_bleMasterSlaveOutput_t *output = (rfc_bleMasterSlaveOutput_t *)conn->output_buf;
990 uint8_t tx_buffers_sent;
992 LOG_DBG(
"BLE-HAL: conn rx process start\n");
997 tx_buffers_sent = output->nTxEntryDone - conn->tx_buffers_sent;
998 if(tx_buffers_sent != 0) {
999 conn->tx_buffers_sent = output->nTxEntryDone;
1001 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME_BLE_TX_EVENT);
1002 NETSTACK_MAC.
input();
1006 connection_rx(conn);
1009 if(conn->counter == conn->conn_update_counter) {
1011 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME_BLE_CONNECTION_UPDATED);
1012 NETSTACK_MAC.
input();
void oscillators_request_hf_xosc(void)
Requests the HF XOSC as the source for the HF clock, but does not perform the actual switch...
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
ble_result_t(* reset)(void)
Resets the BLE controller.
int rtimer_set(struct rtimer *rtimer, rtimer_clock_t time, rtimer_clock_t duration, rtimer_callback_t func, void *ptr)
Post a real-time task.
#define PROCESS(name, strname)
Declare a process.
Representation of a real-time task.
void rf_core_setup_interrupts(bool poll_mode)
Setup RF core interrupts.
Header file with macros which rename TI CC26xxware functions.
void packetbuf_clear(void)
Clear and reset the packetbuf.
void rf_ble_cmd_create_adv_params(uint8_t *param, dataQueue_t *rx_queue, uint8_t adv_data_len, uint8_t *adv_data, uint8_t scan_resp_data_len, uint8_t *scan_resp_data, ble_addr_type_t own_addr_type, uint8_t *own_addr)
Creates BLE radio command parameters that are used to enable BLE advertisement on the radio core...
int process_is_running(struct process *p)
Check if a process is running.
ble_result_t(* set_adv_enable)(unsigned short enable)
Enables/disables advertising.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
#define PROCESS_BEGIN()
Define the beginning of a process.
void ble_addr_to_eui64(uint8_t *dst, uint8_t *src)
Copy the node's BLE address to a destination memory area and converts it into a EUI64 address in the ...
#define PROCESS_END()
Define the end of a process.
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
The structure of a ble radio controller driver in Contiki.
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
Header file with declarations for the I/O Control module.
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
ble_result_t(* read_adv_channel_tx_power)(short *power)
Reads the used power on the advertisement channels.
unsigned short rf_ble_cmd_send(uint8_t *command)
Sends a BLE radio command to the radio.
Header file for the CC13xx/CC26xx RF core driver.
const linkaddr_t linkaddr_null
The null link-layer address.
static uint8_t output(const linkaddr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
BLE commands for the TI CC26xx BLE radio.
Driver for the retrieval of an BLE address from flash.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
#define RTIMER_NOW()
Get the current clock time.
Header file for the CC13xx/CC26xx oscillator control.
unsigned short rf_ble_cmd_setup_ble_mode(void)
Initializes the radio core to be used as a BLE radio.
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
void(* input)(void)
Callback for getting notified of incoming packet.
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
hardware abstraction for a BLE controller
void rf_ble_cmd_create_slave_params(uint8_t *params, dataQueue_t *rx_queue, dataQueue_t *tx_queue, uint32_t access_address, uint8_t crc_init_0, uint8_t crc_init_1, uint8_t crc_init_2, uint32_t win_size, uint32_t window_widening, uint8_t first_packet)
Creates BLE radio command parameters that are used to setup a single BLE connection event on the radi...
int(* off)(void)
Turn the radio off.
ble_result_t(* set_adv_data)(unsigned short data_len, char *data)
Sets the advertising data.
Header file for the real-time timer module.
ble_result_t(* set_adv_param)(unsigned int adv_interval, ble_adv_type_t type, ble_addr_type_t own_addr_type, unsigned short adv_channel_map)
Sets the parameter for advertising.
Header file for the Contiki process interface.
ble_result_t(* read_bd_addr)(uint8_t *addr)
Reads the static BLE device address.
ble_result_t(* read_buffer_size)(unsigned int *buf_len, unsigned int *num_buf)
Reads the size of the data buffers.
unsigned short rf_ble_cmd_wait(uint8_t *command)
Waits for a running BLE radio command to be finished.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
process_event_t process_alloc_event(void)
Allocate a global event number.
unsigned short rf_ble_cmd_add_data_queue_entry(dataQueue_t *q, uint8_t *e)
Adds a data buffer to a BLE transmission queue.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
void ble_addr_cpy_to(uint8_t *dst)
Copy the node's factory BLE address to a destination memory area.
void oscillators_switch_to_hf_xosc(void)
Performs the switch to the XOSC.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Header file for the Packet buffer (packetbuf) management
void rf_ble_cmd_create_slave_cmd(uint8_t *cmd, uint8_t channel, uint8_t *params, uint8_t *output, uint32_t start_time)
Creates a BLE radio command structure that sets up a single BLE connection event when sent to the rad...
#define LPM_MODULE(n, m, s, w, l)
Declare a variable to be used in order to get notifications from LPM.
Include file for the Contiki low-layer network stack (NETSTACK)
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Header file for the logging system
uint8_t rf_core_boot()
Boot the RF Core.
static void input(void)
Process a received 6lowpan packet.
void rf_ble_cmd_create_adv_cmd(uint8_t *command, uint8_t channel, uint8_t *param, uint8_t *output)
Creates a BLE radio command structure that enables BLE advertisement when sent to the radio core...
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
ble_result_t(* connection_update)(unsigned int connection_handle, unsigned int conn_interval, unsigned int conn_latency, unsigned int supervision_timeout)
Updates the connection parameters.
int(* on)(void)
Turn the radio on.
void process_start(struct process *p, process_data_t data)
Start a process.
void lpm_register_module(lpm_registered_module_t *module)
Register a module for LPM notifications.
ble_result_t(* set_scan_resp_data)(unsigned short data_len, char *data)
Sets the scan response data.