[platform][cc13xx] TI CC13xx MCU w/ sub-GHz radio initial support

This commit is contained in:
Brian Swetland
2016-03-03 14:02:58 -08:00
parent 0143e97c6e
commit a3bc8b8c90
11 changed files with 1020 additions and 0 deletions

49
platform/cc13xx/debug.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <kernel/thread.h>
#include <platform/debug.h>
#include <driverlib/uart.h>
#define UART0_BASE 0x40001000
void platform_dputc(char c) {
UARTCharPut(UART0_BASE, c);
}
int platform_dgetc(char *c, bool wait) {
int n;
for (;;) {
if ((n = UARTCharGetNonBlocking(UART0_BASE)) < 0) {
if (wait) {
thread_yield();
} else {
return -1;
}
} else {
*c = n;
return 0;
}
}
}

49
platform/cc13xx/gpio.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <dev/gpio.h>
#include <driverlib/gpio.h>
#include <driverlib/ioc.h>
int gpio_config(unsigned nr, unsigned flags) {
if (flags & GPIO_INPUT) {
IOCPortConfigureSet(nr, IOC_PORT_GPIO, IOC_INPUT_ENABLE);
} else {
IOCPortConfigureSet(nr, IOC_PORT_GPIO, 0);
}
if (flags & GPIO_OUTPUT) {
GPIO_setOutputEnableDio(nr, GPIO_OUTPUT_ENABLE);
} else {
GPIO_setOutputEnableDio(nr, GPIO_OUTPUT_DISABLE);
}
return 0;
}
void gpio_set(unsigned nr, unsigned on) {
GPIO_writeDio(nr, on);
}
int gpio_get(unsigned nr) {
return GPIO_readDio(nr);
}

View File

@@ -0,0 +1,34 @@
DEFIRQ(aon_gpio_edge)
DEFIRQ(i2c)
DEFIRQ(rfc_cpe_1)
DEFIRQ(unused0)
DEFIRQ(aon_rtc_comb)
DEFIRQ(uart0_comb)
DEFIRQ(aux_swev0)
DEFIRQ(ssi0_comb)
DEFIRQ(ssi1_comb)
DEFIRQ(rfc_cpe_0)
DEFIRQ(rfc_hw_comb)
DEFIRQ(rfc_cmd_ack)
DEFIRQ(i2s)
DEFIRQ(aux_swev1)
DEFIRQ(wdt)
DEFIRQ(gpt0a)
DEFIRQ(gpt0b)
DEFIRQ(gpt1a)
DEFIRQ(gpt1b)
DEFIRQ(gpt2a)
DEFIRQ(gpt2b)
DEFIRQ(gpt3a)
DEFIRQ(gpt3b)
DEFIRQ(crypto_result_avail)
DEFIRQ(dma_done_comb)
DEFIRQ(dma_err)
DEFIRQ(flash)
DEFIRQ(swev0)
DEFIRQ(aux_comb)
DEFIRQ(aon_prog0)
DEFIRQ(prog0)
DEFIRQ(aux_compa)
DEFIRQ(aux_adc)
DEFIRQ(trng)

View File

@@ -0,0 +1,19 @@
#pragma once
#define __NVIC_PRIO_BITS 3
#define DEFIRQ(x) x##_IRQn,
typedef enum {
Reset_IRQn = -15,
NonMaskableInt_IRQn = -14,
HardFault_IRQn = -13,
MemoryManagement_IRQn = -12,
BusFault_IRQn = -11,
UsageFault_IRQn = -10,
SVCall_IRQn = -5,
DebugMonitor_IRQn = -4,
PendSV_IRQn = -2,
SysTick_IRQn = -1,
#include <platform/defirq.h>
} IRQn_Type;
#undef DEFIRQ

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <platform/ti-rf.h>
#include <platform/ti-rf-prop.h>
void radio_init(void);
uint32_t radio_send_cmd(uint32_t cmd);
void radio_wait_cmd(uint16_t *status);

View File

@@ -0,0 +1,169 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
// Standard Packet Format
// [ Preamble ][ Sync Word ][ Length Field ][ Address ][ Payload ][ CRC ]
// 0-30 bytes 0-32 bytes opt byte opt byte 0-255 opt 16bit
#define CMD_PROP_TX 0x3801
#define CMD_PROP_RX 0x3802
#define CMD_PROP_TX_ADV 0x3803
#define CMD_PROP_RX_ADV 0x3804
#define CMD_PROP_CS 0x3805 // cc13xx only
#define CMD_PROP_RADIO_SETUP 0x3806 // cc26xx only
#define CMD_PROP_RADIO_DIV_SETUP 0x3807 // cc13xx only
#define CMD_PROP_SET_LEN 0x3401
#define CMD_PROP_RESTART_RX 0x3402
#define PROP_DONE_OK 0x3400
#define PROP_DONE_RXTIMEOUT 0x3401
#define PROP_DONE_BREAK 0x3402 // tx abort due to timeout
#define PROP_DONE_ENDED 0x3403 // rx end trigger
#define PROP_DONE_STOPPED 0x3404 // stopped by CMD_STOP
#define PROP_DONE_ABORT 0x3405 // stopped by CMD_ABORT
#define PROP_DONE_RXERR 0x3406 // crc error
#define PROP_DONE_IDLE 0x3407 // CS ended because idle (cc13xx only)
#define PROP_DONE_BUSY 0x3408 // CS ended because busy (cc13xx only)
#define PROP_DONE_IDLETIMEOUT 0x3409 // CS (cc13xx only)
#define PROP_DONE_BUSYTIMEOUT 0x3409 // CS (cc13xx only)
#define PROP_ERROR_PAR 0x3800 // illegal parameter
#define PROP_ERROR_TXBUF 0x3801 // no available tx buffer at sop
#define PROP_ERROR_RXFULL 0x3802 // out of rx buffers during rx
#define PROP_ERROR_NO_SETUP 0x3803 // radio not in proprietary mode
#define PROP_ERROR_NO_FS 0x3804 // freq synth was off
#define PROP_ERROR_RXOVF 0x3805 // rx overflow
#define PROP_ERROR_TXUNF 0x3806 // tx underflow
typedef struct rf_op_prop_tx rf_op_prop_tx_t;
typedef struct rf_op_prop_tx_adv rf_op_prop_tx_adv_t;
typedef struct rf_op_prop_rx rf_op_prop_rx_t;
typedef struct rf_prop_output rf_prop_output_t;
#define PROP_TX_FS_ON (0 << 0) // leave freq synth on after
#define PROP_TX_FS_OFF (1 << 0) // turn freq synth off after
#define PROP_TX_USE_CRC (1 << 3) // append CRC to packet
#define PROP_TX_VAR_LEN (1 << 4) // send pkt_len as first byte
struct rf_op_prop_tx {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint8_t config;
uint8_t pkt_len;
uint32_t sync_word;
void *data;
};
#define PROP_TXA_FS_ON (0 << 0) // leave freq synth on after
#define PROP_TXA_FS_OFF (1 << 0) // turn off freq synth after
#define PROP_TXA_USE_CRC (1 << 3) // append crc to packet
#define PROP_TXA_CRC_INC_SW (1 << 4) // include sync word in crc calc
#define PROP_TXT_CRC_INC_HDR (1 << 5) // include header in crc calc
struct rf_op_prop_tx_adv {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint8_t config;
uint8_t num_hdr_bits; // 0-32
uint16_t pkt_len; // 0 = unlimited
uint8_t start_conf; // 0
uint8_t pre_trig; // trigger for preamble->sync, NOW = one preamble
uint32_t pre_time;
uint32_t sync_word;
void *data; // packet data, or TX queue for unlimited length
};
#define PROP_RX_FS_ON (0 << 0) // leave freq synth on after
#define PROP_RX_FS_OFF (1 << 0) // turn off freq synth after
#define PROP_RX_REPEAT_OK (1 << 1) // continue receiving after success
#define PROP_RX_REPEAT_NOT_OK (1 << 2) // continue receiving after failure
#define PROP_RX_USE_CRC (1 << 3) // check crc
#define PROP_RX_VAR_LEN (1 << 4) // first byte is packet length
#define PROP_RX_CHECK_ADDRESS (1 << 5)
#define PROP_RX_END_STOP (1 << 6) // packet discarded if end trg during rx
#define PROP_RX_KEEP_BAD_ADDR (1 << 7) // receive (but mark ignored) if addr mismatch
#define PROP_RX_AUTOFLUSH_IGNORED (1 << 0) // discard ignored packets
#define PROP_RX_AUTOFLUSH_CRC_ERR (1 << 1) // discard CRC error packets
#define PROP_RX_INC_HDR (1 << 3) // include header byte in rxdata
#define PROP_RX_INC_CRC (1 << 4) // include crc field in rxdata
#define PROP_RX_INC_RSSI (1 << 5) // include rssi byte
#define PROP_RX_INC_TIMESTAMP (1 << 6) // include timestamp word
#define PROP_RX_INC_STATUS (1 << 7) // include status byte
#define PROP_STATUS_ADDR_INDEX_MASK 0x1F
#define PROP_STATUS_ALT_SYNC_WORD 0x20
#define PROP_STATUS_MASK 0xC0
#define PROP_STATUS_RX_OK 0x00
#define PROP_STATUS_CRC_ERR 0x40
#define PROP_STATUS_IGNORE 0x80
#define PROP_STATUS_EX_ABORTED 0xC0
struct rf_op_prop_rx {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint8_t config;
uint8_t rx_config;
uint32_t sync_word;
uint8_t max_pkt_len; // 0 = unknown/unlimited
uint8_t addr0;
uint8_t addr1;
uint8_t end_trig;
uint32_t end_time;
rf_queue_t *queue;
rf_prop_output_t *output;
};
struct rf_prop_output {
uint16_t num_rx_ok;
uint16_t num_rx_err;
uint8_t num_rx_ignored; // ignored due to addr mismatch
uint8_t num_rx_stopped; // rx fail due to addr mismatch or bad length
uint8_t num_rx_full; // discarded due to lack of buffer space
uint8_t last_rssi; // rssi at last sync word match
uint32_t timestamp; // of last rx'd packet
};
STATIC_ASSERT(sizeof(rf_op_prop_tx_t) == 24);
STATIC_ASSERT(sizeof(rf_op_prop_tx_adv_t) == 32);
STATIC_ASSERT(sizeof(rf_op_prop_rx_t) == 36);
//STATIC_ASSERT(sizeof(rf_op_prop_rx_adv_t) == 48);
STATIC_ASSERT(sizeof(rf_prop_output_t) == 12);

View File

@@ -0,0 +1,333 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <compiler.h>
// trigger control byte (TRM 23.3.2.5.1)
#define TRG_NOW 0x00
#define TRG_NEVER 0x01 // except for CMD_TRIGGER if enabled
#define TRG_ABSTIME 0x02
#define TRG_REL_SUBMIT 0x03 // relative to command submission time
#define TRG_REL_START 0x04 // relative to command start (end trg only)
#define TRG_REL_PREVSTART 0x05 // relative to start of previous command
#define TRG_REL_FIRSTSTART 0x06 // relative to first command in chain
#define TRG_REL_PREVEND 0x07 // relative to end of previous command
#define TRG_REL_EVT1 0x08 // relative to prev command evt1
#define TRG_REL_EVT2 0x09 // relative to prev command evt1
#define TRG_EXTERNAL 0x0A // TRG_EXT_* in timer parameter
#define TRG_ENA_CMD_O 0x10 // CMD_TRIGGER #0 enabled as alt trigger
#define TRG_ENA_CMD_1 0x30 // CMD_TRIGGER #1 enabled as alt trigger
#define TRG_ENA_CMD_2 0x50 // CMD_TRIGGER #2 enabled as alt trigger
#define TRG_ENA_CMD_3 0x70 // CMD_TRIGGER #3 enabled as alt trigger
#define TRG_PAST_OK 0x80 // trigger in the past happens asap
#define TRG_PAST_DISALLOW 0x00 // never happens, or for start trg is an error
#define TRG_EXT_RISING 0x00
#define TRG_EXT_FALLING 0x40
#define TRG_EXT_BOTH_EDGE 0x80
#define TRG_SRC_RFC_GPI0 (22 << 8)
#define TRG_SRC_RFC_GPI1 (23 << 8)
// condition byte (TRM 23.3.2.5.2)
// - commands return TRUE, FALSE, or ABORT as defined for each command
// - a skip of 0 = re-exec current, 1 = exec next, 2 = skip next
#define CND_ALWAYS 0x00
#define CND_NEVER 0x01
#define CND_STOP_ON_FALSE 0x02
#define CND_STOP_ON_TRUE 0x03
#define CND_SKIP_ON_FALSE 0x04 // if false, skip N commands
#define CND_SKIP_ON_TRUE 0x05 // if true, skip N commands
#define CND_SKIP(n) (((n) & 0xF) << 4)
#define QE_STATUS_PENDING 0x00 // set before submitting by SysCPU
#define QE_STATUS_ACTIVE 0x01 // entry in queue by RadioCPU
#define QE_STATUS_BUSY 0x02 // entry is actively being r/w by RadioCPU
#define QE_STATUS_DONE 0x03 // RadioCPU is done, SysCPU may reclaim
#define QE_CONFIG_GENERAL 0x00
#define QE_CONFIG_MULTI 0x01
#define QE_CONFIG_POINTER 0x02
#define QE_CONFIG_LEN_SZ_0 0x00 // no length prefix
#define QE_CONFIG_LEN_SZ_1 0x04 // 1-byte length prefix
#define QE_CONFIG_LEN_SZ_2 0x08 // 2-byte length prefix
typedef struct rf_queue rf_queue_t;
typedef struct rf_queue_entry rf_queue_entry_t;
struct rf_queue {
rf_queue_entry_t *curr;
rf_queue_entry_t *last;
};
struct rf_queue_entry {
rf_queue_entry_t *next;
uint8_t status;
uint8_t config;
uint16_t length;
union {
uint8_t data[4];
uint8_t *ptr;
};
};
#define IMM_CMD(cmd,arg,ext) (((cmd) << 16) | \
((arg & 0xFF) << 8) | \
((ext & 0x3F) << 2) | \
0x01)
// direct commands
#define CMD_ABORT 0x0401 // stop asap
#define CMD_STOP 0x0402 // stop once active rx/tx completes
#define CMD_GET_RSSI 0x0403
#define CMD_TRIGGER 0x0404
#define CMD_TRIGGER_N(n) (0x0404 | (((n) & 3) << 16))
#define CMD_START_RAT 0x0405
#define CMD_PING 0x0406 // no op
// immediate commands
#define CMD_UPDATE_RADIO_SETUP 0x0001
#define CMD_GET_FW_INFO 0x0002
#define CMD_READ_RFREG 0x0601
#define CMD_SET_RAT_CMP 0x000A
#define CMD_SET_RAT_CPT 0x0603
#define CMD_DISABLE_RAT_CH 0x0408
#define CMD_SET_RAT_OUTPUT 0x0604
#define CMD_ARM_RAT_CH 0x0409
#define CMD_DISARM_RAT_CH 0x040A
#define CMD_SET_TX_POWER 0x0010
#define CMD_UPDATE_FS 0x0011
#define CMD_BUS_REQUEST 0x040E
#define CMD_ADD_DATA_ENTRY 0x0005
#define CMD_REMOVE_DATA_ENTRY 0x0006
#define CMD_FLUSH_QUEUE 0x0007
#define CMD_CLEAR_RX 0x0008
#define CMD_REMOVE_PENDING 0x0009
// queued commands
#define CMD_NOP 0x0801 // rf_op_basic_t
#define CMD_FS 0x0803 // rf_op_fs_t
#define CMD_FS_OFF 0x0804 // rf_op_basic_t
#define CMD_RADIO_SETUP 0x0802 // rf_op_radio_setup_t
#define CMD_FS_POWERUP 0x080C // rf_op_fs_power_t
#define CMD_FS_POWERDOWN 0x080D // rf_op_fs_power_t
#define CMD_SYNC_STOP_RAT 0x0809 // rf_op_sync_rat_t
#define CMD_SYNC_START_RAT 0x080A // rf_op_sync_rat_t
#define CMD_COUNT 0x080B // rf_op_count_t
#define CMD_PATTERN_CHECK 0x0813 // rf_op_pattern_check_t
// status
#define DONE_OK 0x0400 // success
#define DONE_COUNTDOWN 0x0401 // count == 0
#define DONE_RXERR 0x0402 // crc error
#define DONE_TIMEOUT 0x0403
#define DONE_STOPPED 0x0404 // stopped by CMD_DONE
#define DONE_ABORT 0x0405 // stopped by CMD_ABORT
#define DONE_FAILED 0x0406
#define ERROR_PAST_START 0x0800 // start trigger is in the past
#define ERROR_START_TRIG 0x0801 // bad trigger parameter
#define ERROR_CONDITION 0x0802 // bad condition parameter
#define ERROR_PAR 0x0803 // invalid parameter (command specific)
#define ERROR_POINTER 0x0804 // invalid pointer to next op
#define ERROR_CMD_ID 0x0805 // bad command id
#define ERROR_WRONG_BG 0x0806 // fg cmd cannot run w/ active bg cmd
#define ERROR_NO_SETUP 0x0807 // tx/rx without radio setup
#define ERROR_NO_FS 0x0808 // tx/rx with freq synth off
#define ERROR_SYNTH_PROG 0x0809 // freq synth calibration failure
#define ERROR_TXUNF 0x080A // tx underflow
#define ERROR_TXOVF 0x080B // rx overflow
#define ERROR_NO_RX 0x080C // no rx data available
#define ERROR_PENDING 0x080D // other commands already pending
typedef struct rf_op_basic rf_op_basic_t;
typedef struct rf_op_radio_setup rf_op_radio_setup_t;
typedef struct rf_op_fs rf_op_fs_t;
typedef struct rf_op_fs_power rf_op_fs_power_t;
typedef struct rf_op_sync_rat rf_op_sync_rat_t;
typedef struct rf_op_count rf_op_count_t;
typedef struct rf_op_pattern_check rf_op_pattern_check_t;
typedef struct rf_op_fw_info rf_op_fw_info_t;
struct rf_op_basic {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
} __PACKED;
struct rf_op_fw_info {
uint16_t cmd;
uint16_t version;
uint16_t free_ram_start;
uint16_t free_ram_size;
uint16_t avail_rat_ch;
} __PACKED;
#if 0
// warning - docs / headers disagree
#define RF_MODE_BLE 0x00
#define RF_MODE_802_15_4 0x01
#define RF_MODE_2MBPS_GFSK 0x02
#define RF_MODE_5MBPS_8FSK 0x05
#define RF_MODE_NO_CHANGE 0xFF
#endif
#define RF_CFG_FE_MODE(n) ((n) & 7)
#define RF_CFG_INT_BIAS (0 << 3)
#define RF_CFG_EXT_BIAS (1 << 3)
#define RF_CFG_FS_POWERUP (0 << 10)
#define RF_CFG_FS_NO_POWERUP (1 << 10)
#define TX_PWR_IB(n) ((n) & 0x3F)
#define TX_PWR_GC(n) (((n) & 3) << 6)
#define TX_PWR_TEMP_COEFF(n) (((n) & 0xFF) << 8)
struct rf_op_radio_setup {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint8_t mode;
uint8_t io_div; // cc13xx (0,2,5,6,10,12,5,30), cc26xx (0,2)
uint16_t config;
uint16_t tx_pwr;
void *reg_override;
} __PACKED;
struct rf_op_fs {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint16_t frequency;
uint16_t fract_freq;
uint8_t synth_conf;
uint8_t reserved;
uint8_t mid_precal;
uint8_t kt_precal;
uint16_t tdc_precal;
};
struct rf_op_fs_power {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint16_t reserved;
void *reg_override;
};
struct rf_op_sync_rat {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint16_t reserved;
uint32_t rat0;
};
// - on start, if count == 0 -> ERROR_PARAM (ABORT?), else count--
// - if count > 0, status = DONE_OK, res = TRUE
// - if count == 0, status = DONE_COUNTDOWN, res = FALSE
struct rf_op_count {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint16_t counter;
};
#define PTN_OP_EQ (0 << 0)
#define PTN_OP_LT (1 << 0)
#define PTN_OP_GT (2 << 0)
#define PTN_BYTE_REV (1 << 2) // 0=LE, 1=BE
#define PTN_BIT_REV (1 << 3)
#define PTN_SIGN_EXT(n) (((n) & 31) << 4)
#define PTN_USE_IDX (1 << 9)
#define PTN_USE_PTR (0 << 9)
// 1. read word x from pointer or index from start of last committed rx data
// 2. byteswap x, if requested
// 3. bitswap x, if requested
// 4. x = x & mask
// 5. if sign extend != 0, extend that bit through 31
// 6. result = x OP value
// if result TRUE, status = DONE_OK
// if result FALSE, status = DONE_FAILED
// if USE_IDX but no RX data available, status = ERROR_NO_RX, result = ABORT
struct rf_op_pattern_check {
uint16_t cmd;
uint16_t status;
void *next_op;
uint32_t start_time;
uint8_t start_trig;
uint8_t cond;
uint16_t pattern;
void *next_op_if_true;
union {
void *ptr;
int32_t idx;
};
uint32_t mask;
uint32_t value;
};
// multi element is <COUNT:2> [ <NEXT-DATA-INDEX:2> <DATA:1> ... ]
STATIC_ASSERT(sizeof(rf_queue_t) == 8);
STATIC_ASSERT(sizeof(rf_queue_entry_t) == 12);
STATIC_ASSERT(sizeof(rf_op_basic_t) == 14);
STATIC_ASSERT(sizeof(rf_op_radio_setup_t) == 24);
STATIC_ASSERT(sizeof(rf_op_fs_t) == 24);
STATIC_ASSERT(sizeof(rf_op_fs_power_t) == 20);
STATIC_ASSERT(sizeof(rf_op_sync_rat_t) == 20);
STATIC_ASSERT(sizeof(rf_op_count_t) == 16);
STATIC_ASSERT(sizeof(rf_op_pattern_check_t) == 32);
STATIC_ASSERT(sizeof(rf_op_fw_info_t) == 10);

80
platform/cc13xx/init.c Normal file
View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <platform.h>
#include <arch/arm/cm.h>
#include <driverlib/prcm.h>
#include <driverlib/ioc.h>
#include <driverlib/uart.h>
#include <driverlib/osc.h>
// if GPIO_UART_?R are defined, route UART there
#include <target/gpioconfig.h>
void trimDevice(void);
#define UART0_BASE 0x40001000
void platform_early_init(void) {
trimDevice();
PRCMPowerDomainOn(PRCM_DOMAIN_SERIAL);
while (PRCMPowerDomainStatus(PRCM_DOMAIN_SERIAL) != PRCM_DOMAIN_POWER_ON) ;
PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_ON) ;
PRCMPeripheralRunEnable(PRCM_PERIPH_UART0);
PRCMPeripheralRunEnable(PRCM_PERIPH_GPIO);
PRCMLoadSet();
#ifdef GPIO_UART_TX
IOCPortConfigureSet(GPIO_UART_TX, IOC_PORT_MCU_UART0_TX, 0);
#endif
#ifdef GPIO_UART_RX
IOCPortConfigureSet(GPIO_UART_RX, IOC_PORT_MCU_UART0_RX, IOC_INPUT_ENABLE);
#endif
UARTConfigSetExpClk(UART0_BASE, 48000000, 115200,
UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE);
UARTEnable(UART0_BASE);
arm_cm_systick_init(48000000);
// switch to 24MHz XOSC
OSCInterfaceEnable();
OSCClockSourceSet(OSC_SRC_CLK_HF, OSC_XOSC_HF);
OSCHfSourceSwitch();
#if 0
dprintf(INFO, "hf clk src %d\n", OSCClockSourceGet(OSC_SRC_CLK_HF));
dprintf(INFO, "mf clk src %d\n", OSCClockSourceGet(OSC_SRC_CLK_MF));
dprintf(INFO, "lf clk src %d\n", OSCClockSourceGet(OSC_SRC_CLK_LF));
#endif
}
void platform_init(void) {
}

176
platform/cc13xx/radio.c Normal file
View File

@@ -0,0 +1,176 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app.h>
#include <debug.h>
#include <reg.h>
#include <kernel/thread.h>
#include <kernel/event.h>
#include <arch/arm/cm.h>
#include <driverlib/prcm.h>
#include <driverlib/rfc.h>
#include <driverlib/rf_mailbox.h>
#include <inc/hw_rfc_dbell.h>
#include <rf_patches/rf_patch_cpe_genfsk.h>
#include <platform/radio.h>
#define RADIO_POLLED_MODE 0
#define CPE0_MASK (IRQ_BOOT_DONE | IRQ_RX_OK | IRQ_LAST_COMMAND_DONE | IRQ_COMMAND_DONE)
static event_t ack_evt = EVENT_INITIAL_VALUE(ack_evt, 0, EVENT_FLAG_AUTOUNSIGNAL);
static event_t cpe0_evt = EVENT_INITIAL_VALUE(cpe0_evt, 0, EVENT_FLAG_AUTOUNSIGNAL);
void ti_cc_rfc_cpe_0_irq(void) {
arm_cm_irq_entry();
event_signal(&cpe0_evt, false);
// disable IRQ until thread handles and re-enables them in response to event
NVIC_DisableIRQ(rfc_cpe_0_IRQn);
// reschedule if we woke a thread (indicated by !signalled)
arm_cm_irq_exit(!cpe0_evt.signalled);
}
static inline uint32_t cpe0_reason(void) {
uint32_t n = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFCPEIFG) & CPE0_MASK;
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFCPEIFG) = ~n;
return n;
}
static inline uint32_t cpe0_wait_irq(void) {
NVIC_EnableIRQ(rfc_cpe_0_IRQn);
event_wait(&cpe0_evt);
return cpe0_reason();
}
void ti_cc_rfc_cpe_1_irq(void) {
arm_cm_irq_entry();
}
void ti_cc_rfc_cmd_ack_irq(void) {
arm_cm_irq_entry();
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
event_signal(&ack_evt, false);
// reschedule if we woke a thread (indicated by !signalled)
arm_cm_irq_exit(!ack_evt.signalled);
}
uint32_t radio_send_cmd(uint32_t cmd) {
#if RADIO_POLLED_MODE
while (HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) != 0) {}
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
while (!HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG)) {}
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
return HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
#else
while(HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) != 0) {}
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
event_unsignal(&ack_evt);
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
event_wait(&ack_evt);
#endif
return HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
}
void radio_wait_cmd(uint16_t *status) {
uint32_t addr = (uint32_t) status;
uint16_t val;
#if RADIO_POLLED_MODE
for (;;) {
val = *REG16(addr);
if (val < 3) {
// idle, waiting to start, or running
thread_yield();
} else {
break;
}
}
#else
for (;;) {
uint32_t x = cpe0_wait_irq();
val = *REG16(addr);
if (val > 3) {
break;
}
}
#endif
if ((val != 0x0400) && (val != 0x3400)) {
dprintf(INFO, "Cmd Status %04x\n", val);
}
}
void radio_init(void) {
#if !RADIO_POLLED_MODE
// route all IRQs to CPE0
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFCPEISL) = 0;
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFCPEIEN) = CPE0_MASK;
// clear any pending
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFCPEIFG) = 0;
HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
//NVIC_EnableIRQ(rfc_cpe_0_IRQn);
//NVIC_EnableIRQ(rfc_cpe_1_IRQn);
NVIC_EnableIRQ(rfc_cmd_ack_IRQn);
#endif
// Power RF domain
PRCMPowerDomainOn(PRCM_DOMAIN_RFCORE);
while (PRCMPowerDomainStatus(PRCM_DOMAIN_RFCORE) != PRCM_DOMAIN_POWER_ON) ;
dprintf(INFO, "power on\n");
// enable the RF top clock
PRCMDomainEnable(PRCM_DOMAIN_RFCORE);
PRCMLoadSet();
dprintf(INFO, "top clock on\n");
// enable all RF sub clocks
RFCClockEnable();
dprintf(INFO, "clocks on\n");
thread_sleep(1000);
rf_patch_cpe_genfsk();
dprintf(INFO, "patched\n");
unsigned n = radio_send_cmd(IMM_CMD(CMD_PING, 0, 0));
dprintf(INFO, "RESPONSE %08x\n", n);
n = radio_send_cmd(IMM_CMD(CMD_PING, 0, 0));
dprintf(INFO, "RESPONSE %08x\n", n);
rf_op_fw_info_t fwinfo;
memset(&fwinfo, 0, sizeof(fwinfo));
fwinfo.cmd = CMD_GET_FW_INFO;
n = radio_send_cmd((uint32_t) &fwinfo);
dprintf(INFO, "FW %d %04x %04x %04x %04x\n",
n, fwinfo.version, fwinfo.free_ram_start,
fwinfo.free_ram_size, fwinfo.avail_rat_ch);
n = radio_send_cmd(IMM_CMD(CMD_START_RAT, 0, 0));
dprintf(INFO, "START RAT %d\n", n);
}

30
platform/cc13xx/rules.mk Normal file
View File

@@ -0,0 +1,30 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
ARCH := arm
ARM_CPU := cortex-m3
MEMBASE := 0x20000000
ROMBASE := 0x00000000
MEMSIZE := 0x5000
MODULE_SRCS += \
$(LOCAL_DIR)/init.c \
$(LOCAL_DIR)/debug.c \
$(LOCAL_DIR)/vectab.c \
$(LOCAL_DIR)/gpio.c \
$(LOCAL_DIR)/radio.c
LINKER_SCRIPT += \
$(BUILDDIR)/system-twosegment.ld
MODULE_DEPS += \
arch/arm/arm-m/systick \
platform/cc13xx/cc13xxware
GLOBAL_COMPILEFLAGS += -DWITH_NO_FP=1
#GLOBAL_COMPILEFLAGS += -DDISABLE_DEBUG_OUTPUT=1
include make/module.mk

46
platform/cc13xx/vectab.c Normal file
View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2016 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <compiler.h>
#include <arch/arm/cm.h>
static void ti_cc_dummy_irq(void) {
arm_cm_irq_entry();
panic("unhandled irq");
}
#define DEFAULT_HANDLER(x) \
void ti_cc_##x##_irq(void) __WEAK_ALIAS("ti_cc_dummy_irq")
#define DEFIRQ(n) DEFAULT_HANDLER(n);
#include <platform/defirq.h>
#undef DEFIRQ
#define VECTAB_ENTRY(x) ti_cc_##x##_irq
const void * const __SECTION(".text.boot.vectab2") vectab2[] = {
#define DEFIRQ(n) VECTAB_ENTRY(n),
#include <platform/defirq.h>
#undef DEFIRQ
};