diff --git a/feeds/bluetooth-cc2652/cc2652/Makefile b/feeds/bluetooth-cc2652/cc2652/Makefile new file mode 100755 index 000000000..26a9abd68 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/Makefile @@ -0,0 +1,43 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=cc2652 +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/cc2652 + SECTION:=utils + CATEGORY:=Utilities + TITLE:=cc2652 -- TI CC26x2 firmware upgrade tool + DEPENDS:=+libstdcpp +zlib +endef + +define Package/cc2652/description + TI CC26x2 firmware upgrade tool +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Package/cc2652/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/tisbl.init $(1)/etc/init.d/tisbl + + $(INSTALL_DIR) $(1)/etc/tifirmware + $(INSTALL_BIN) ./files/firmware/* $(1)/etc/tifirmware/ + + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tisbl $(1)/usr/bin/ + $(INSTALL_BIN) ./files/*.sh $(1)/usr/bin/ + + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_BIN) ./files/tisbl.config $(1)/etc/config/tisbl +endef + +$(eval $(call BuildPackage,cc2652)) + diff --git a/feeds/bluetooth-cc2652/cc2652/files/ble-scan-rx-parser.sh b/feeds/bluetooth-cc2652/cc2652/files/ble-scan-rx-parser.sh new file mode 100755 index 000000000..a7050d058 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/ble-scan-rx-parser.sh @@ -0,0 +1,124 @@ +#!/usr/bin/lua +--[[ +ByteCnt: 1 1 1 2 1 4 + ---- --------- ---------- ----- ------ ------- +FieldName:Type EventCode DataLength Event Status EventId +--]] + +--Type +Command = 0x01 +Event = 0x04 + +--OpCode +GapScan_enable = 0xFE51 + +--EventCode +HCI_LE_ExtEvent = 0xff + +--Status +SUCCESS = 0x00 + +--Event +GAP_HCI_ExtentionCommandStatus = 0x067F +GAP_AdvertiserScannerEvent = 0x0613 + +--EventId +GAP_EVT_ADV_REPORT = 0x00400000 +GAP_EVT_SCAN_ENABLED = 0x00010000 + +local write = io.write +function print(...) + local n = select("#",...) + for i = 1,n do + local v = tostring(select(i,...)) + write(v) + if i~=n then write'\t' end + end +-- write'\n' +end + +function printf(str, ...) + return print(str:format(...)) +end + +function lshift(x, by) + return x * 2 ^ by +end + +function GetUint8(Payload, position) + return string.byte(Payload, position) +end + +function GetUint32(Payload, position) + return (lshift(string.byte(Payload, position+3),24) + lshift(string.byte(Payload, position+2),16) + lshift(string.byte(Payload, position+1),8) + string.byte(Payload, position)) +end + +function GetUint16(Payload, position) + return (lshift(string.byte(Payload, position+1),8) + string.byte(Payload, position)) +end + +function hexdump(Payload,separator) + for i=1,Payload:len(), 1 do + io.write(string.format("%02X", Payload:byte(i))) + if (i< Payload:len()) then + io.write(separator) + end + end +end + +ibeacon_hdr=string.char(0x1A,0xFF,0x4C,0x00,0x02,0x15) + +function DumpAdvertiserData(Payload) +--[[ +Len(1byte)+Type(1byte)+Data(Len bytes) +--]] + while( Payload:len() > 0 ) do + local Len = GetUint8(Payload,1) + if (GetUint8(Payload,2) == 0xff) then -- manufacturer data + print(" MFR=") + hexdump(Payload:sub(1,Len+1),'') + if (Payload:sub(1,6) == ibeacon_hdr) then + print(" [ibeacon]") + end + end + Payload = string.sub(Payload,Len+2,-1) + end +end + +function DumpAdvertiserScannerEvent(Payload) + local Status = GetUint8(Payload,3) + local EventId = GetUint32(Payload,4) + if((EventId==GAP_EVT_ADV_REPORT) and (Status==SUCCESS)) + then + local MAC = string.sub(Payload,10,15) + local TxPower = GetUint8(Payload,19) + local RSSI = GetUint8(Payload,20) + printf("MAC=%02X%02X%02X%02X%02X%02X RSI=%d PWR=%d",string.byte(MAC,6),string.byte(MAC,5),string.byte(MAC,4), + string.byte(MAC,3),string.byte(MAC,2),string.byte(MAC,1),RSSI,TxPower) + local DataLength = GetUint16(Payload,30) + DumpAdvertiserData(string.sub(Payload,32,-1)) + print("\n") + end +end + +function hci_event_paser() + while true do + local Header = io.read(3) + if not Header then break end + local EventType = GetUint8(Header,1) + local EventCode = GetUint8(Header,2) + local DataLength = GetUint8(Header,3) + + local Data = io.read(DataLength) + local Event = GetUint16(Data,1) +-- print(EventType,EventCode,DataLength,Event) + if not Data then break end + if(Event==GAP_AdvertiserScannerEvent) + then + DumpAdvertiserScannerEvent(Data) +-- hexdump(ibeacon_hdr) + end + end +end + +hci_event_paser() diff --git a/feeds/bluetooth-cc2652/cc2652/files/blescan.sh b/feeds/bluetooth-cc2652/cc2652/files/blescan.sh new file mode 100755 index 000000000..f188760ed --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/blescan.sh @@ -0,0 +1,8 @@ +#!/bin/sh +com-wr.sh /dev/ttyMSM1 3 "\x01\x1D\xFC\x01\x00" > /dev/null # this command dealy time must >= 3, if small then 3, the following commands will be something wrong +com-wr.sh /dev/ttyMSM1 1 "\x01\x00\xFE\x08\x08\x00\x00\x00\x00\x00\x00\x00" > /dev/null +com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x02" > /dev/null +com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x03" > /dev/null +com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x04" > /dev/null +com-wr.sh /dev/ttyMSM1 1 "\x01\x61\xFE\x02\x01\x05" > /dev/null +com-wr.sh /dev/ttyMSM1 3 "\x01\x51\xFE\x06\x00\x00\xF4\x01\x28\x00" | tee /tmp/blescan.data | ble-scan-rx-parser.sh \ No newline at end of file diff --git a/feeds/bluetooth-cc2652/cc2652/files/com-wr.sh b/feeds/bluetooth-cc2652/cc2652/files/com-wr.sh new file mode 100755 index 000000000..10c07c8c2 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/com-wr.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# com-wr.sh tty time command parser +# example com-wr.sh /dev/ttyMSM1 1 "\x01\x1D\xFC\x01\x00" | hexdump.sh --> send "\x01\x1D\xFC\x01\x00" to /dev/ttyMSM1 and then hexdump receive data until 100ms timeout +#command example "\x7E\x03\xD0\xAF und normaler Text" +tty=$1 +time=$2 +command=$3 +parser=$4 +stty -F $tty time $time +exec 99< $tty +echo -en $command > $tty +cat $tty +exec 99<&- diff --git a/feeds/bluetooth-cc2652/cc2652/files/firmware/ble5_host_test_bd9.bin b/feeds/bluetooth-cc2652/cc2652/files/firmware/ble5_host_test_bd9.bin new file mode 100755 index 000000000..0d69b476a Binary files /dev/null and b/feeds/bluetooth-cc2652/cc2652/files/firmware/ble5_host_test_bd9.bin differ diff --git a/feeds/bluetooth-cc2652/cc2652/files/firmware/blinky_bd9.bin b/feeds/bluetooth-cc2652/cc2652/files/firmware/blinky_bd9.bin new file mode 100755 index 000000000..192e14b5b Binary files /dev/null and b/feeds/bluetooth-cc2652/cc2652/files/firmware/blinky_bd9.bin differ diff --git a/feeds/bluetooth-cc2652/cc2652/files/firmware/multi_role_bd9.bin b/feeds/bluetooth-cc2652/cc2652/files/firmware/multi_role_bd9.bin new file mode 100755 index 000000000..188924b30 Binary files /dev/null and b/feeds/bluetooth-cc2652/cc2652/files/firmware/multi_role_bd9.bin differ diff --git a/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_broadcaster_bd9.bin b/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_broadcaster_bd9.bin new file mode 100755 index 000000000..275793a49 Binary files /dev/null and b/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_broadcaster_bd9.bin differ diff --git a/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_central_bd9.bin b/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_central_bd9.bin new file mode 100755 index 000000000..f6448a1fa Binary files /dev/null and b/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_central_bd9.bin differ diff --git a/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_peripheral_bd9.bin b/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_peripheral_bd9.bin new file mode 100755 index 000000000..ebb5dcac0 Binary files /dev/null and b/feeds/bluetooth-cc2652/cc2652/files/firmware/simple_peripheral_bd9.bin differ diff --git a/feeds/bluetooth-cc2652/cc2652/files/firmware/znp_bd9.bin b/feeds/bluetooth-cc2652/cc2652/files/firmware/znp_bd9.bin new file mode 100755 index 000000000..01a832bbd Binary files /dev/null and b/feeds/bluetooth-cc2652/cc2652/files/firmware/znp_bd9.bin differ diff --git a/feeds/bluetooth-cc2652/cc2652/files/hexdump.sh b/feeds/bluetooth-cc2652/cc2652/files/hexdump.sh new file mode 100755 index 000000000..b3ec7b078 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/hexdump.sh @@ -0,0 +1,11 @@ +#!/usr/bin/lua +local block = 16 +while true do + local bytes = io.read(block) + if not bytes then break end + for b in string.gfind(bytes, ".") do + io.write(string.format("%02X ", string.byte(b))) + end + io.write(string.rep(" ", block - string.len(bytes) + 1)) + io.write(string.gsub(bytes, "%c", "."), "\n") +end diff --git a/feeds/bluetooth-cc2652/cc2652/files/ibeacon-broadcaster.sh b/feeds/bluetooth-cc2652/cc2652/files/ibeacon-broadcaster.sh new file mode 100755 index 000000000..5e4cecd43 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/ibeacon-broadcaster.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# script---------------- UUID---------------------------------------------------------------------- MAJOR----- MINOR----- POWER- +#example: ibeacon-broadcaster.sh "\xE2\x0A\x39\xF4\x73\xF5\x4B\xC4\xA1\x2F\x17\xD1\xAD\x07\xA9\x61" "\x01\x23" "\x45\x67" "\xC8" +if [ "$#" -eq 4 ]; then + UUID=$1 + MAJOR=$2 + MINOR=$3 + POWER=$4 +else + UUID="\xE2\x0A\x39\xF4\x73\xF5\x4B\xC4\xA1\x2F\x17\xD1\xAD\x07\xA9\x61" + MAJOR="\x01\x23" + MINOR="\x45\x67" + POWER="\xC8" +fi + +com-wr.sh /dev/ttyMSM1 3 "\x01\x1D\xFC\x01\x00" > /dev/null # this command dealy time must >= 3, if small then 3, the following commands will be something wrong +com-wr.sh /dev/ttyMSM1 1 "\x01\x00\xFE\x08\x01\x00\x00\x00\x00\x00\x00\x00" > /dev/null +com-wr.sh /dev/ttyMSM1 1 "\x01\x3E\xFE\x15\x12\x00\xA0\x00\x00\xA0\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x7F\x01\x01\x00" > /dev/null +com-wr.sh /dev/ttyMSM1 1 "\x09\x44\xFE\x23\x00\x00\x00\x1E\x00\x02\x01\x1A\x1A\xFF\x4C\x00\x02\x15${UUID}${MAJOR}${MINOR}${POWER}\x00" > /dev/null +com-wr.sh /dev/ttyMSM1 1 "\x01\x3F\xFE\x04\x00\x00\x00\x00" | hexdump.sh \ No newline at end of file diff --git a/feeds/bluetooth-cc2652/cc2652/files/ti-hosttest2net.sh b/feeds/bluetooth-cc2652/cc2652/files/ti-hosttest2net.sh new file mode 100755 index 000000000..a3b3aae50 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/ti-hosttest2net.sh @@ -0,0 +1,5 @@ +#!/bin/sh +killall -9 ser2net +tisbl.sh /dev/ttyMSM1 115200 2652 /etc/tifirmware/ble5_host_test_bd9.bin 79 34 +echo "7000:telnet:0:/dev/ttyMSM1:115200 8DATABITS NONE 1STOPBIT remctl" > /tmp/ser2net.conf +ser2net -c /tmp/ser2net.conf diff --git a/feeds/bluetooth-cc2652/cc2652/files/tisbl.config b/feeds/bluetooth-cc2652/cc2652/files/tisbl.config new file mode 100755 index 000000000..84242e4fc --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/tisbl.config @@ -0,0 +1,9 @@ +config tisbl 'tisbl' + option firmware '/etc/tifirmware/ble5_host_test_bd9.bin' + option tty '/dev/ttyMSM1' # for EAP101 board +# option tty '/dev/ttyACM0' # for virtualbox openwrt 19.07 with TI CC26X2R launchpad + option tichip '2652' + option baudrate '115200' + option resetpin '79' + option backdoorpin '34' #EAP101-R1 +# option backdoorpin '67' #EAP101-R0A-HW-modification diff --git a/feeds/bluetooth-cc2652/cc2652/files/tisbl.init b/feeds/bluetooth-cc2652/cc2652/files/tisbl.init new file mode 100755 index 000000000..a9cdf963d --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/tisbl.init @@ -0,0 +1,21 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2007 OpenWrt.org + +#start after dbus (60) +START=62 +USE_PROCD=1 + +start_service() { + firmware="$(uci -q get tisbl.tisbl.firmware)" + tty="$(uci -q get tisbl.tisbl.tty)" + tichip="$(uci -q get tisbl.tisbl.tichip)" + baudrate="$(uci -q get tisbl.tisbl.baudrate)" + resetpin="$(uci -q get tisbl.tisbl.resetpin)" + backdoorpin="$(uci -q get tisbl.tisbl.backdoorpin)" + tisbl.sh $tty $baudrate $tichip $firmware $resetpin $backdoorpin +} + +service_triggers() +{ + procd_add_reload_trigger "tisbl" +} diff --git a/feeds/bluetooth-cc2652/cc2652/files/tisbl.sh b/feeds/bluetooth-cc2652/cc2652/files/tisbl.sh new file mode 100755 index 000000000..1d22160d2 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/files/tisbl.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# tisbl.sh $tty $baudrate $tichip $firmware $resetpin $backdoorpin +# tisbl.sh /dev/ttyMSM1 115200 2652 /etc/tifirmware/blinky_bd13.bin 79 67 + +#assumption: resetpin and backdoorpin are low active +tty=$1 +baudrate=$2 +tichip=$3 +firmware=$4 +resetpin=$5 +backdoorpin=$6 + +ti_reset() #assumption:resetpin is low active +{ + if [ ! -e /sys/class/gpio/gpio${resetpin} ]; then + echo ${resetpin} > /sys/class/gpio/export + fi + echo out > /sys/class/gpio/gpio${resetpin}/direction + + echo 1 > /sys/class/gpio/gpio${resetpin}/value + echo 0 > /sys/class/gpio/gpio${resetpin}/value + sleep 1 + echo 1 > /sys/class/gpio/gpio${resetpin}/value +} + +ti_goto_bootloader() #assumption:backdoorpin is low active +{ + if [ ! -e /sys/class/gpio/gpio${backdoorpin} ]; then + echo ${backdoorpin} > /sys/class/gpio/export + fi + echo out > /sys/class/gpio/gpio${backdoorpin}/direction + + echo 0 > /sys/class/gpio/gpio${backdoorpin}/value + ti_reset + sleep 1 + echo 1 > /sys/class/gpio/gpio${backdoorpin}/value +} + +if [ -e $firmware ]; then + ti_goto_bootloader + tisbl $tty $baudrate $tichip $firmware #try to upgrade firmware +fi + diff --git a/feeds/bluetooth-cc2652/cc2652/src/Makefile b/feeds/bluetooth-cc2652/cc2652/src/Makefile new file mode 100755 index 000000000..f63c016b1 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/Makefile @@ -0,0 +1,27 @@ +# Executable +EXE = tisbl + +# Compiler, Linker Defines +#CC = g++ +#CFLAGS = -w -O -Wno-deprecated -I. -fpermissive -std=gnu++0x +#CFLAGS = -I. -fpermissive -Wwrite-strings -lstdc++ +CFLAGS = -I. -Wwrite-strings -std=gnu++0x -lstdc++ -fPIC +#CFLAGS = -I. -lstdc++ -Wwrite-strings -std=gnu++0x +#LIBS = +#LDFLAGS = $(LIBS) + +# Compile and Assemble C++ Source Files into Object Files +%.o: %.cpp + $(CXX) $(CFLAGS) $(LDFLAGS) -c $< -o $@ +# Source and Object files +SRC = $(wildcard *.cpp) +OBJ = $(patsubst %.cpp, %.o, $(SRC)) + +# Link all Object Files with external Libraries into Binaries +$(EXE): $(OBJ) + $(CC) $(CFLAGS) $(OBJ) $(LDFLAGS) -o $(EXE) +# $(CC) $(CFLAGS) $(OBJ) $(LDFLAGS) -o $(EXE) -lz + +.PHONY: clean +clean: + -rm -f $(EXE) *.o diff --git a/feeds/bluetooth-cc2652/cc2652/src/debug.h b/feeds/bluetooth-cc2652/cc2652/src/debug.h new file mode 100755 index 000000000..b352ac0d6 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/debug.h @@ -0,0 +1,13 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include +#define DEBUG 0 +#if defined(DEBUG) && DEBUG > 0 + #define DEBUG_PRINT(fmt, args...) fprintf(stderr, "$$%d:%s:%d:%s():" fmt, \ + (int)time(NULL), __FILE__, __LINE__, __func__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */ +#endif + +#endif // __DEBUG_H__ \ No newline at end of file diff --git a/feeds/bluetooth-cc2652/cc2652/src/sblAppEx.cpp b/feeds/bluetooth-cc2652/cc2652/src/sblAppEx.cpp new file mode 100755 index 000000000..d4638fe2a --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sblAppEx.cpp @@ -0,0 +1,257 @@ +/****************************************************************************** +* Filename: sblAppEx.cpp +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader Library application example. +* This example enumerates all COM devices and lets you +* select which port to connect to. The example assumes the +* connected device is a CC2538, CC2650 or CC2652 and programs +* a blinky onto the device. After programming the blinky, +* bootloader mode may be forced by +* - holding SELECT button on 06EB (for CC2538 and CC26x0 EMKs), or +* - holding BTN-1 on the device LaunchPad (for CC26x2 LPs) +* when resetting the chip. +* +* Copyright (C) 2013 - 2019 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ +#include "serialib.h" +#include "sbllib.h" +#include +#include +#include + +//#include + +using namespace std; + +// Calculate crc32 checksum the way CC2538 and CC2650 does it. +int calcCrcLikeChip(const unsigned char *pData, unsigned long ulByteCount) +{ + unsigned long d, ind; + unsigned long acc = 0xFFFFFFFF; + const unsigned long ulCrcRand32Lut[] = + { + 0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, + 0x76DC4190, 0x6B6B51F4, 0x4DB26158, 0x5005713C, + 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C, + 0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C + }; + + while ( ulByteCount-- ) + { + d = *pData++; + ind = (acc & 0x0F) ^ (d & 0x0F); + acc = (acc >> 4) ^ ulCrcRand32Lut[ind]; + ind = (acc & 0x0F) ^ (d >> 4); + acc = (acc >> 4) ^ ulCrcRand32Lut[ind]; + } + + return (acc ^ 0xFFFFFFFF); +} + +/// Application status function (used as SBL status callback) +void appStatus(char *pcText, bool bError) +{ + if(bError) + { + cerr << pcText; + } + else + { + cout << pcText; + } +} + + +/// Application progress function (used as SBL progress callback) +static void appProgress(uint32_t progress) +{ + fprintf(stdout, "\r%d%% ", progress); + fflush(stdout); +} + +// Defines +// Name Hex Dec +// ------------------------------- --------------- --------------------------------- +#define DEVICE_CC2538 0x2538 // 9528 +#define DEVICE_CC26X0 0x2650 // 9808 +#define DEVICE_CC2640R2 0x2640 // 9792 +#define DEVICE_CC26X2 0x2652 // 9810 +#define CC2538_FLASH_BASE 0x00200000 +#define CC26XX_FLASH_BASE 0x00000000 + +// Application main function +// tisbl SerialDevNode baudRate deviceType firmware +int main(int argc, char *argv[]) +{ + // START: Program Configuration + /* UART baud rate. Default: 230400 */ + uint32_t baudRate = 115200; + uint32_t deviceType = DEVICE_CC26X2; + SblDevice *pDevice = NULL; // Pointer to SblDevice object + char *SerialDevNode; + int32_t devStatus = -1; // Hold SBL status codes + std::string fileName; // File name to program + uint32_t byteCount = 0; // File size in bytes + uint32_t fileCrc, devCrc; // Variables to save CRC checksum + uint32_t devFlashBase; // Flash start address + static std::vector pvWrite(1);// Vector to application firmware in. + static std::ifstream file; // File stream + + // Set callback functions + SblDevice::setCallBackStatusFunction(&appStatus); + SblDevice::setCallBackProgressFunction(&appProgress); + + // Select device + // deviceType FlashBase File + // DEVICE_CC2538 CC2538_FLASH_BASE blinky_backdoor_select_btn2538.bin + // DEVICE_CC26X0 CC26XX_FLASH_BASE blinky_backdoor_select_btn2650.bin + // DEVICE_CC2640R2 CC26XX_FLASH_BASE blinky_backdoor_select_btn2640r2.bin + // DEVICE_CC26X2 CC26XX_FLASH_BASE blinky_backdoor_select_btn26x2.bin + if(argc < 5) { + return -1; + } + SerialDevNode = argv[1]; + baudRate = atoi(argv[2]); + deviceType = strtol(argv[3], NULL, 16); + fileName = argv[4]; + switch(deviceType) + { + case DEVICE_CC2538: + devFlashBase = CC2538_FLASH_BASE; + break; + case DEVICE_CC26X0: + case DEVICE_CC2640R2: + case DEVICE_CC26X2: + devFlashBase = CC26XX_FLASH_BASE; + break; + } + printf("SerialDevNode=%s, baudRate=%d, deviceType=%04x, fileName=%s\n",SerialDevNode,baudRate,deviceType,fileName.c_str()); + + // Should SBL try to enable XOSC? (Not possible for CC26xx) + bool bEnableXosc = false; + if(deviceType == DEVICE_CC2538) + { + char answer[64]; + cout << "Enable device CC2538 XOSC? (Y/N): "; + cin >> answer; + bEnableXosc = (answer[0] == 'Y' || answer[0] == 'y') ? true : false; + } + + // Create SBL object + pDevice = SblDevice::Create(deviceType); + if(pDevice == NULL) + { + printf("No SBL device object.\n"); + cout << "\n\nAn error occurred: " << pDevice->getLastStatus(); + return -1; + } + + // Connect to device + printf("Connecting (%s @ %d baud) ...\n", SerialDevNode, baudRate); + if(pDevice->connect(SerialDevNode, baudRate, bEnableXosc) != SBL_SUCCESS) + { + cout << "\n\nAn error occurred: " << pDevice->getLastStatus(); + return -1; + } + + // Read file + file.open(fileName.c_str(), std::ios::binary); + if(file.is_open()) + { + // Get file size: + file.seekg(0, std::ios::end); + byteCount = (uint32_t)file.tellg(); + file.seekg(0, std::ios::beg); + + // Read data + pvWrite.resize(byteCount); + file.read((char*) &pvWrite[0], byteCount); + } + else + { + cout << "Unable to open file " << fileName.c_str(); + cout << "\n\nAn error occurred: " << pDevice->getLastStatus(); + return -1; + } + + // Calculate file CRC checksum + fileCrc = calcCrcLikeChip((unsigned char *)&pvWrite[0], byteCount); + + if(pDevice->calculateCrc32(devFlashBase, byteCount, &devCrc) != SBL_SUCCESS) + { + cout << "\n\nAn error occurred: " << pDevice->getLastStatus(); + return -1; + } + printf ("pre-Comparing CRC: fileCrc=%x,devCrc=%x\n",fileCrc,devCrc); + + if(fileCrc == devCrc) { + cout << "CRC is same, no need to upgrade\n"; + pDevice->reset(); + return 0; + } + + // Erasing as much flash needed to program firmware. + cout << "Erasing flash ...\n"; + if(pDevice->eraseFlashRange(devFlashBase, byteCount) != SBL_SUCCESS) + { + cout << "\n\nAn error occurred: " << pDevice->getLastStatus(); + return -1; + } + + // Writing file to device flash memory. + cout << "Writing flash ...\n"; + if(pDevice->writeFlashRange(devFlashBase, byteCount, &pvWrite[0]) != SBL_SUCCESS) + { + cout << "\n\nAn error occurred: " << pDevice->getLastStatus(); + return -1; + } + + // Calculate CRC checksum of flashed content. + cout << "Calculating CRC on device ...\n"; + if(pDevice->calculateCrc32(devFlashBase, byteCount, &devCrc) != SBL_SUCCESS) + { + cout << "\n\nAn error occurred: " << pDevice->getLastStatus(); + return -1; + } + + // Compare CRC checksums + printf ("Comparing CRC: fileCrc=%x,devCrc=%x\n",fileCrc,devCrc); + if(fileCrc == devCrc) printf("OK\n"); + else printf("Mismatch!\n"); + + cout << "Resetting device ...\n"; + pDevice->reset(); + cout << "OK\n"; + +} \ No newline at end of file diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device.cpp b/feeds/bluetooth-cc2652/cc2652/src/sbl_device.cpp new file mode 100755 index 000000000..e6db4b270 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device.cpp @@ -0,0 +1,673 @@ +/****************************************************************************** +* Filename: sbl_device.cpp +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader device file. +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include +#include "sbl_device.h" +#include "sbl_device_cc2538.h" +#include "sbl_device_cc2650.h" +#include "sbl_device_cc2652.h" + +#if 0 + #include + #include +#else + #include "serialib.h" +#endif + +#include + +// Static variables +// +std::string SblDevice::sm_csLastError; +uint32_t SblDevice::sm_progress = 0; +tProgressFPTR SblDevice::sm_pProgressFunction = NULL; +tStatusFPTR SblDevice::sm_pStatusFunction = NULL; +uint32_t SblDevice::sm_chipType = 0; + +//----------------------------------------------------------------------------- +/** \brief Constructor +*/ +//----------------------------------------------------------------------------- +SblDevice::SblDevice() +{ + m_pCom = NULL; + m_lastDeviceStatus = -1; + m_lastSblStatus = SBL_SUCCESS; + m_bCommInitialized = false; + m_deviceId = 0; + m_ramSize = 0; + m_flashSize = 0; + m_pageEraseSize = 0; +} + + +//----------------------------------------------------------------------------- +/** \brief Destructor +*/ +//----------------------------------------------------------------------------- +SblDevice::~SblDevice() +{ + if (m_pCom != nullptr) + { + delete m_pCom; + m_pCom = nullptr; + } + + m_lastDeviceStatus = -1; + m_bCommInitialized = false; + m_ramSize = -1; + m_flashSize = -1; +} + + +//----------------------------------------------------------------------------- +/** \brief Create Serial Bootloader Device +* +* \param[in] ui32ChipType +* Chip type the object should be created for, e.g. 0x2650 for CC2650. +*/ +//----------------------------------------------------------------------------- +/*static*/SblDevice * +SblDevice::Create(uint32_t ui32ChipType) +{ + if (ui32ChipType == 0) + { + return NULL; + } + + sm_chipType = ui32ChipType; + + switch (ui32ChipType) + { + case 0x2538: + return (SblDevice *)new SblDeviceCC2538(); + case 0x1350: + case 0x1310: + case 0x2670: + case 0x2650: + case 0x2640: + case 0x2630: + case 0x2620: + return (SblDevice *)new SblDeviceCC2650(); + case 0x1312: + case 0x1352: + case 0x2642: + case 0x2652: + return (SblDevice *)new SblDeviceCC2652(); + default: + return NULL; + } +} + + +#if 0 +//----------------------------------------------------------------------------- +/** \brief Enumerate COM port devices +* +* \param[in/out] pComPortElements +* Pointer to array where enumerated COM devices are stored +* \param[in/out] numElements +* Maximum number of elements to enumerate. Is populated with number +* of devices enumerated. +* +* \return +* +*/ +//----------------------------------------------------------------------------- +/*static*/uint32_t +SblDevice::enumerate(ComPortElement *pComPortElements, int &numElements) +{ + ComPort com; + if (com.enumerate(pComPortElements, numElements) != ComPort::COMPORT_SUCCESS) + { + printf("Failed to enumerate COM devices.\n"); + return SBL_ENUM_ERROR; + } + + return SBL_SUCCESS; +} +#endif +//----------------------------------------------------------------------------- +/** \brief Connect to given port number at specified baud rate. +* +* \param[in] csPortNum +* String containing the COM port to use +* \param[in] ui32BaudRate +* Baud rate to use for talking to the device. +* \param[in] bEnableXosc (optional) +* If true, try to enable device XOSC. Defaults to false. This option is +* not available for all device types. +* +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDevice::connect(std::string csPortNum, uint32_t ui32BaudRate, + bool bEnableXosc/* = false*/) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + + // + // Check input arguments + // + if (csPortNum.empty() || ui32BaudRate == 0) + { + setState(SBL_ARGUMENT_ERROR, "Cannot connect. Port number '%s' or baud rate '%d' is invalid.\n", + csPortNum.c_str(), ui32BaudRate); + return SBL_ARGUMENT_ERROR; + } + + // Try to connect to the specified port at the specified baud rate + if (m_pCom != NULL) + { + // Try to open port +#if 1 + char result = m_pCom->openDevice(csPortNum.c_str(),ui32BaudRate); + if(result < 0) + { + setState(SBL_PORT_ERROR, "SBL: Unable to open %s. Error: %d.\n", csPortNum.c_str(), result); + return SBL_PORT_ERROR; + } +#else + if (int result = m_pCom->open(csPortNum, + ui32BaudRate, + SBL_DEFAULT_READ_TIMEOUT, + SBL_DEFAULT_WRITE_TIMEOUT) != ComPort::COMPORT_SUCCESS) + { + setState(SBL_PORT_ERROR, "SBL: Unable to open %s. Error: %d.\n", csPortNum.c_str(), result); + return SBL_PORT_ERROR; + } +#endif + m_csComPort = csPortNum; + m_baudRate = ui32BaudRate; + } + // Check if device is responding at the given baud rate + if ((retCode = initCommunication(bEnableXosc)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Read device ID + // + uint32_t tmp; + if ((retCode = readDeviceId(&tmp)) != SBL_SUCCESS) + { + setState(retCode, "Failed to read device ID during initial connect.\n"); + return retCode; + } + // + // Read device flash size + // + if ((retCode = readFlashSize(&tmp)) != SBL_SUCCESS) + { + setState(retCode, "Failed to read flash size during initial connect.\n"); + return retCode; + } + // + // Read device ram size + // + if ((retCode = readRamSize(&tmp)) != SBL_SUCCESS) + { + setState(retCode, "Failed to read RAM size during initial connect.\n"); + return retCode; + } + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Send auto baud. +* +* \param[out] bBaudSetOk +* True if response is ACK, false otherwise +* +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDevice::sendAutoBaud(bool &bBaudSetOk) +{ + DEBUG_PRINT("\n"); + bBaudSetOk = false; + // + // Send 0x55 0x55 and expect ACK + // + char pData[2]; + memset(pData, 0x55, 2); + if (m_pCom->writeBytes(pData, 2) != 2) + { + setState(SBL_PORT_ERROR, "Communication initialization failed. Failed to send data.\n"); + return SBL_PORT_ERROR; + } + + if (getCmdResponse(bBaudSetOk, 2, true) != SBL_SUCCESS) + { + // No response received. Invalid baud rate? + setState(SBL_PORT_ERROR, "No response from device. Device may not be in bootloader mode. Reset device and try again.\nIf problem persists, check connection and baud rate.\n"); + return SBL_PORT_ERROR; + } + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Get ACK/NAK from the boot loader. +* +* \param[out] bAck +* True if response is ACK, false if response is NAK. +* \param[in] ui32MaxRetries (optional) +* How many times ComPort::readBytes() can time out before fail is issued. +* \param[in] bQuietTimeout (optional) +* Do not set error if no command response is received. +* +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDevice::getCmdResponse(bool &bAck, + uint32_t ui32MaxRetries/* = SBL_DEFAULT_RETRY_COUNT*/, + bool bQuietTimeout/* = false*/) +{ + DEBUG_PRINT("\n"); + unsigned char pIn[2]; + memset(pIn, 0, 2); + uint32_t numBytes = 0; + uint32_t retry = 0; + bAck = false; + uint32_t bytesRecv = 0; + + // + // Expect 2 bytes (ACK or NAK) + // + do + { + numBytes = m_pCom->readBytes(pIn, 2); + bytesRecv += numBytes; + retry++; + } while ((bytesRecv < 2) && (retry < ui32MaxRetries)); + + if (bytesRecv < 2) + { + if (!bQuietTimeout) setState(SBL_TIMEOUT_ERROR, "Timed out waiting for ACK/NAK. No response from device.\n"); + return SBL_TIMEOUT_ERROR; + } + else + { + if (pIn[0] == 0x00 && pIn[1] == 0xCC) + { + bAck = true; + return setState(SBL_SUCCESS); + } + else if (pIn[0] == 0x00 && pIn[1] == 0x33) + { + return setState(SBL_SUCCESS); + } + else + { + setState(SBL_ERROR, "ACK/NAK not received. Expected 0x00 0xCC or 0x00 0x33, received 0x%02X 0x%02X. bytesRecv=%d\n", pIn[0], pIn[1], bytesRecv); + return SBL_ERROR; + } + } + return SBL_ERROR; +} + + +//----------------------------------------------------------------------------- +/** \brief Send command response (ACK/NAK). +* +* \param[in] bAck +* True if response is ACK, false if response is NAK. +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDevice::sendCmdResponse(bool bAck) +{ + DEBUG_PRINT("\n"); + // + // Send response + // + char pData[2]; + pData[0] = 0x00; + pData[1] = (bAck) ? 0xCC : 0x33; + + if (m_pCom->writeBytes(pData, 2) != 2) + { + setState(SBL_PORT_ERROR, "Failed to send ACK/NAK response over %s\n", + m_csComPort.c_str()); + return SBL_PORT_ERROR; + } + return SBL_SUCCESS; +} + +//----------------------------------------------------------------------------- +/** \brief Get response data from device. +* +* \param[out] pcData +* Pointer to where received data will be stored. +* \param[in|out] ui32MaxLen +* Max number of bytes that can be received. Is populated with the actual +* number of bytes received. +* \param[in] ui32MaxRetries (optional) +* How many times ComPort::readBytes() can time out before fail is issued. +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDevice::getResponseData(char *pcData, uint32_t &ui32MaxLen, + uint32_t ui32MaxRetries/* = SBL_DEFAULT_RETRY_COUNT*/) +{ + DEBUG_PRINT("\n"); + uint32_t numBytes = 0; + uint32_t retry = 0; + unsigned char pcHdr[2]; + uint32_t numPayloadBytes; + uint8_t hdrChecksum, dataChecksum; + uint32_t bytesRecv = 0; + + setState(SBL_SUCCESS); + // + // Read length and checksum + // + memset(pcHdr, 0, 2); + do + { + bytesRecv += m_pCom->readBytes(&pcHdr[bytesRecv], (2 - bytesRecv)); + retry++; + } while ((bytesRecv < 2) && retry < ui32MaxRetries); + + // + // Check that we've received 2 bytes + // + if (bytesRecv < 2) + { + setState(SBL_TIMEOUT_ERROR, "Timed out waiting for data header from device.\n"); + return SBL_TIMEOUT_ERROR; + } + numPayloadBytes = pcHdr[0] - 2; + hdrChecksum = pcHdr[1]; + + // + // Check if length byte is too long. + // + if (numPayloadBytes > ui32MaxLen) + { + setState(SBL_ERROR, "Error: Device sending more data than expected. \nMax expected was %d, sent was %d.\n", (uint32_t)ui32MaxLen, (numPayloadBytes + 2)); +#if 1 + m_pCom->flushReceiver(); +#endif + return SBL_ERROR; + } + + // + // Read the payload data + // + bytesRecv = 0; + do + { + bytesRecv += m_pCom->readBytes(&pcData[bytesRecv], (numPayloadBytes - bytesRecv)); + retry++; + } while (bytesRecv < numPayloadBytes && retry < ui32MaxRetries); + + // + // Have we received what we expected? + // + if (bytesRecv < numPayloadBytes) + { + ui32MaxLen = bytesRecv; + setState(SBL_TIMEOUT_ERROR, "Timed out waiting for data from device.\n"); + return SBL_TIMEOUT_ERROR; + } + + // + // Verify data checksum + // + dataChecksum = generateCheckSum(0, pcData, numPayloadBytes); + if (dataChecksum != hdrChecksum) + { + setState(SBL_ERROR, "Checksum verification error. Expected 0x%02X, got 0x%02X.\n", hdrChecksum, dataChecksum); + return SBL_ERROR; + } + + ui32MaxLen = bytesRecv; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Are we connected to the device? +* +* \return +* Returns true if connected to device. +* Returns false if not connected to device. +*/ +//----------------------------------------------------------------------------- +bool +SblDevice::isConnected() +{ + DEBUG_PRINT("\n"); + if (!m_pCom) + { + return false; + } + return true; +} + + +//----------------------------------------------------------------------------- +/** \brief This function generates the bootloader protocol checksum. +* +* \param[in] ui32Cmd +* The bootloader command +* \param[in] pcData +* Pointer to the command data. +* \param[in] ui32DataLen +* Data length in bytes. +* +* \return +* Returns the generated checksum. +*/ +//----------------------------------------------------------------------------- +uint8_t +SblDevice::generateCheckSum(uint32_t ui32Cmd, const char *pcData, + uint32_t ui32DataLen) +{ + DEBUG_PRINT("\n"); + uint8_t ui8CheckSum = (uint8_t)ui32Cmd; + for (uint32_t i = 0; i < ui32DataLen; i++) + { + ui8CheckSum += pcData[i]; + } + return ui8CheckSum; +} + + +//----------------------------------------------------------------------------- +/** \brief This function sets the SBL status and the SBL error string. +* +* \param[in] ui32Status +* The new SBL status. SBL_SUCCESS, SBL_ERROR, ... +* \param[in] pcFormat +* 'printf' like format string. +* \param[in] ... +* Input variables to the \e pcFormat string. +* +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDevice::setState(const uint32_t &ui32Status, char *pcFormat, ...) +{ + DEBUG_PRINT("\n"); + va_list args; + char text[2048]; + + m_lastSblStatus = ui32Status; + + // Attempt to do a sanity check. Not possible to say how long + // the formatted text will be, but if we reserve half the space for + // formatted arguments it should be sufficient. + if (strlen(pcFormat) > 2048 / 2) { + return SBL_ERROR; + } + + va_start(args, pcFormat); +#if 0 + vsprintf_s(text, pcFormat, args); +#else + vsprintf(text, pcFormat, args); +#endif + sm_csLastError = text; + va_end(args); + + if (SblDevice::sm_pStatusFunction != NULL) + { + bool error = (m_lastSblStatus == SBL_SUCCESS) ? false : true; + sm_pStatusFunction((char *)sm_csLastError.c_str(), error); + } + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Utility function for converting 4 elements in char array into +* 32 bit variable. Data are converted MSB, that is. \e pcSrc[0] is the +* most significant byte. +* +* \param pcSrc[in] +* A pointer to the source array. +* +* \return +* Returns the 32 bit variable. +*/ +//----------------------------------------------------------------------------- +/*static */uint32_t +SblDevice::charArrayToUL(const char *pcSrc) +{ + DEBUG_PRINT("\n"); + uint32_t ui32Val = (unsigned char)pcSrc[3]; + ui32Val += (((unsigned long)pcSrc[2]) & 0xFF) << 8; + ui32Val += (((unsigned long)pcSrc[1]) & 0xFF) << 16; + ui32Val += (((unsigned long)pcSrc[0]) & 0xFF) << 24; + return (ui32Val); +} + + +//----------------------------------------------------------------------------- +/** \brief Utility function for splitting 32 bit variable into char array +* (4 elements). Data are converted MSB, that is, \e pcDst[0] is the +* most significant byte. +* +* \param[in] ui32Src +* The 32 bit variable to convert. +* +* \param[out] pcDst +* Pointer to the char array where the data will be stored. +* +* \return +* void +*/ +//----------------------------------------------------------------------------- +/*static */void +SblDevice::ulToCharArray(const uint32_t ui32Src, char *pcDst) +{ + DEBUG_PRINT("\n"); + // MSB first + pcDst[0] = (uint8_t)(ui32Src >> 24); + pcDst[1] = (uint8_t)(ui32Src >> 16); + pcDst[2] = (uint8_t)(ui32Src >> 8); + pcDst[3] = (uint8_t)(ui32Src >> 0); +} + + +//----------------------------------------------------------------------------- +/** \brief Utility function for swapping the byte order of a 4B char array. +* +* \param[in|out] pcArray +* The char array to byte swap. +* +* \return +* void +*/ +//----------------------------------------------------------------------------- +/*static */void +SblDevice::byteSwap(char *pcArray) +{ + DEBUG_PRINT("\n"); + uint8_t tmp[2] = { (uint8_t)pcArray[0], (uint8_t)pcArray[1] }; + pcArray[0] = pcArray[3]; + pcArray[1] = pcArray[2]; + pcArray[2] = tmp[1]; + pcArray[3] = tmp[0]; +} + + +//----------------------------------------------------------------------------- +/** \brief This functions sets the SBL progress. +* +* \param[in] ui32Progress +* The current progress, typically in percent [0-100]. +* +* \return +* void +*/ +//----------------------------------------------------------------------------- +/*static*/uint32_t +SblDevice::setProgress(uint32_t ui32Progress) +{ + DEBUG_PRINT("\n"); + if (sm_pProgressFunction) + { + sm_pProgressFunction(ui32Progress); + } + + sm_progress = ui32Progress; + + return SBL_SUCCESS; +} diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device.h b/feeds/bluetooth-cc2652/cc2652/src/sbl_device.h new file mode 100755 index 000000000..8db5aa683 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device.h @@ -0,0 +1,143 @@ +#ifndef __SBL_DEVICE_H__ +#define __SBL_DEVICE_H__ +/****************************************************************************** +* Filename: sbl_device.h +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader device header file. +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ +#include "serialib.h" +// +// Typedefs for callback functions to report status and progress to application +// +typedef void (*tStatusFPTR)(char *pcText, bool bError); +typedef void (*tProgressFPTR)(uint32_t ui32Value); + +class SblDevice +{ +public: + // Constructor + ~SblDevice(); + + // Static functions + static SblDevice *Create(uint32_t ui32ChipType); + virtual uint32_t connect(std::string csPortNum, uint32_t ui32BaudRate, bool bEnableXosc = false); + virtual uint32_t ping() = 0; + virtual uint32_t readStatus(uint32_t *pui32Status) = 0; + virtual uint32_t readDeviceId(uint32_t *pui32DeviceId) = 0; + virtual uint32_t readFlashSize(uint32_t *pui32FlashSize) = 0; + virtual uint32_t readRamSize(uint32_t *pui32RamSize) = 0; + virtual uint32_t run(uint32_t ui32Address) { (void)ui32Address; return SBL_UNSUPPORTED_FUNCTION; }; + virtual uint32_t reset() = 0; + virtual uint32_t eraseFlashRange(uint32_t ui32StartAddress, uint32_t ui32ByteCount) { (void)ui32StartAddress; (void)ui32ByteCount; return 0; }; + virtual uint32_t writeFlashRange(uint32_t ui32StartAddress, uint32_t ui32ByteCount, const char *pcData) { (void)ui32StartAddress; (void)ui32ByteCount; (void)pcData; return 0; }; + virtual uint32_t readMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, uint32_t *pui32Data) = 0; + virtual uint32_t readMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, char *pcData) = 0; + virtual uint32_t writeMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, const uint32_t *pui32Data) = 0; + virtual uint32_t writeMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, const char *pcData) = 0; + virtual uint32_t calculateCrc32(uint32_t ui32StartAddress, uint32_t ui32ByteCount, uint32_t *pui32Crc) = 0; + + // CC2650 specific + virtual uint32_t eraseFlashBank(){ return SBL_UNSUPPORTED_FUNCTION; }; + virtual uint32_t setCCFG(uint32_t ui32Field, uint32_t ui32FieldValue) { (void)ui32Field; (void)ui32FieldValue; return SBL_UNSUPPORTED_FUNCTION; }; + + // CC2538 specific + virtual uint32_t setXosc() { return SBL_UNSUPPORTED_FUNCTION; }; + + // Utility functions + bool isConnected(); + uint32_t getDeviceId() { return m_deviceId; } + uint32_t getFlashSize() { return m_flashSize; } + uint32_t getRamSize() { return m_ramSize; } + uint32_t getBaudRate() { return m_baudRate; } + uint32_t getLastStatus() {return m_lastSblStatus; } + uint32_t getLastDeviceStatus() { return m_lastDeviceStatus; } + uint32_t getPageEraseSize() { return m_pageEraseSize; } + static std::string &getLastError(void) { return sm_csLastError;} + static uint32_t getProgress() { return sm_progress; } + static uint32_t setProgress(uint32_t ui32Progress); + static void setCallBackStatusFunction(tStatusFPTR pSf) {sm_pStatusFunction = pSf; } + static void setCallBackProgressFunction(tProgressFPTR pPf) {sm_pProgressFunction = pPf; } + +protected: + // Constructor + SblDevice(); + + virtual uint32_t initCommunication(bool bSetXosc) = 0; + virtual uint32_t sendCmd(uint32_t ui32Cmd, const char *pcSendData = NULL, uint32_t ui32SendLen = 0) = 0; + virtual uint32_t sendAutoBaud(bool &bBaudSetOk); + virtual uint32_t getCmdResponse(bool &bAck, uint32_t ui32MaxRetries = SBL_DEFAULT_RETRY_COUNT, bool bQuiet = false); + virtual uint32_t sendCmdResponse(bool bAck); + virtual uint32_t getResponseData(char *pcData, uint32_t &ui32MaxLen, uint32_t ui32MaxRetries = SBL_DEFAULT_RETRY_COUNT); + + virtual uint8_t generateCheckSum(uint32_t ui32Cmd, const char *pcData, uint32_t ui32DataLen); + virtual uint32_t addressToPage(uint32_t ui32Address) = 0; + virtual bool addressInRam(uint32_t ui32StartAddress, uint32_t ui32ByteCount = 1) = 0; + virtual bool addressInFlash(uint32_t ui32StartAddress, uint32_t ui32ByteCount = 1) = 0; + + virtual uint32_t getBootloaderEnableAddress() = 0; + + uint32_t setState(const uint32_t &ui32Status) { m_lastSblStatus = ui32Status; return m_lastSblStatus;} + uint32_t setState(const uint32_t &ui32Status, char *pcFormat, ...); + + // Utility + static uint32_t charArrayToUL(const char *pcSrc); + static void ulToCharArray(const uint32_t ui32Src, char *pcDst); + static void byteSwap(char *pcArray); + + serialib *m_pCom; + std::string m_csComPort; + bool m_bCommInitialized; + uint32_t m_baudRate; + + static uint32_t sm_chipType; + uint32_t m_deviceId; + uint32_t m_flashSize; + uint32_t m_ramSize; + uint32_t m_pageEraseSize; + + // Status and progress variables + int32_t m_lastDeviceStatus; + int32_t m_lastSblStatus; + static uint32_t sm_progress; + static std::string sm_csLastError; + static tProgressFPTR sm_pProgressFunction; + static tStatusFPTR sm_pStatusFunction; + +private: + +}; + +#endif // __SBL_DEVICE_H__ diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2538.cpp b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2538.cpp new file mode 100755 index 000000000..5cfb71cd9 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2538.cpp @@ -0,0 +1,1762 @@ +/****************************************************************************** +* Filename: sbl_device_cc2538.cpp +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader device file for CC2538 +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include +#include "sbl_device.h" +#include "sbl_device_cc2538.h" +#include "serialib.h" +//#include + +#include + + +/// Struct used when splitting long transfers +typedef struct { + uint32_t startAddr; + uint32_t byteCount; + uint32_t startOffset; + bool bExpectAck; +} tTransfer; + +//----------------------------------------------------------------------------- +/** \brief Constructor + */ +//----------------------------------------------------------------------------- +SblDeviceCC2538::SblDeviceCC2538() +{ + DEBUG_PRINT("\n"); + m_pageEraseSize = SBL_CC2538_PAGE_ERASE_SIZE; +} + +//----------------------------------------------------------------------------- +/** \brief Destructor + */ +//----------------------------------------------------------------------------- +SblDeviceCC2538::~SblDeviceCC2538() +{ + DEBUG_PRINT("\n"); +} + + +//----------------------------------------------------------------------------- +/** \brief This function sends ping command to device. + * + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::ping() +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bResponse = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_PING)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Get response + // + if((retCode = getCmdResponse(bResponse)) != SBL_SUCCESS) + { + return retCode; + } + + return (bResponse) ? SBL_SUCCESS : SBL_ERROR; +} + + +//----------------------------------------------------------------------------- +/** \brief This function gets status from device. + * + * \param[out] pStatus + * Pointer to where status is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::readStatus(uint32_t *pui32Status) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_GET_STATUS)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive command response data + // + char status = 0; + uint32_t ui32NumBytes = 1; + if((retCode = getResponseData(&status, ui32NumBytes)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + + // + // Respond with ACK + // + sendCmdResponse(true); + + m_lastDeviceStatus = status; + *pui32Status = status; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads device ID. + * + * \param[out] pui32DeviceId + * Pointer to where device ID is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::readDeviceId(uint32_t *pui32DeviceId) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_GET_CHIP_ID)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive response data + // + char pId[4]; + memset(pId, 0, 4); + uint32_t numBytes = 4; + if((retCode = getResponseData(pId, numBytes)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + + if(numBytes != 4) + { + // + // Respond with NAK + // + sendCmdResponse(false); + setState(SBL_ERROR, "Didn't receive 4 B.\n"); + return SBL_ERROR; + } + + // + // Respond with ACK + // + sendCmdResponse(true); + + // + // Store retrieved ID and report success + // + *pui32DeviceId = charArrayToUL(pId); + m_deviceId = *pui32DeviceId; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads device FLASH size in bytes. + * + * \param[out] pui32FlashSize + * Pointer to where FLASH size is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::readFlashSize(uint32_t *pui32FlashSize) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + + // + // Read CC2538 DIECFG0 (contains FLASH size information) + // + uint32_t addr = SBL_CC2538_DIECFG0; + uint32_t value; + if((retCode = readMemory32(addr, 1, &value)) != SBL_SUCCESS) + { + setState((tSblStatus)retCode, "Failed to read device FLASH size: %s", getLastError().c_str()); + return retCode; + } + + // + // Calculate FLASH size (FLASH size bits are at bits [6:4]) + // + value = ((value >> 4) & 0x07); + switch(value) + { + case 1: *pui32FlashSize = 0x20000; break; // 128 KB + case 2: *pui32FlashSize = 0x40000; break; // 256 KB + case 3: *pui32FlashSize = 0x60000; break; // 384 KB + case 4: *pui32FlashSize = 0x80000; break; // 512 KB + case 0: // 64 KB + default:*pui32FlashSize = 0x10000; break; // All invalid values are interpreted as 64 KB + } + + m_flashSize = *pui32FlashSize; + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads device RAM size in bytes. + * + * \param[out] pui32RamSize + * Pointer to where RAM size is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::readRamSize(uint32_t *pui32RamSize) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + + // + // Read CC2538 DIECFG0 (contains RAM size information + // + uint32_t addr = SBL_CC2538_DIECFG0; + uint32_t value; + if((retCode = readMemory32(addr, 1, &value)) != SBL_SUCCESS) + { + setState(retCode, "Failed to read device RAM size: %s", getLastError().c_str()); + return retCode; + } + + // + // Calculate RAM size in bytes (Ram size bits are at bits [9:7]) + // + value = ((value >> 7) & 0x07); + switch(value) + { + case 4: *pui32RamSize = 0x8000; break; // 32 KB + case 0: *pui32RamSize = 0x4000; break; // 16 KB + case 1: *pui32RamSize = 0x2000; break; // 8 KB + default:*pui32RamSize = 0x2000; break; // All invalid values are interpreted as 8 KB + } + + m_ramSize = *pui32RamSize; + + return retCode; +} + + +//----------------------------------------------------------------------------- +/** \brief This function makes the device run from the address given by + * \u ui32Address, transferring execution control away from the + * bootloader. No further bootloader access will be possible. + * + * \parameter[in] ui32Address + * The device address where execution will be transferred to. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::run(uint32_t ui32Address) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Generate payload + // - 4B address + // + char pcPayload[4]; + ulToCharArray(ui32Address, &pcPayload[0]); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_RUN, pcPayload, 4)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Run command NAKed by device.\n"); + return SBL_ERROR; + } + + m_bCommInitialized = false; + return SBL_SUCCESS; + +} + +//----------------------------------------------------------------------------- +/** \brief This function reset the device. Communication to the device must be + * reinitialized after calling this function. + * + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::reset() +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_RESET)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Reset command NAKed by device.\n"); + return SBL_ERROR; + } + + m_bCommInitialized = false; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function erases device flash pages. Starting page is the page + * that includes the address in \e startAddress. Ending page is the page + * that includes the address . CC2538 erase + * size is 2KB. + * + * \param[in] ui32StartAddress + * The start address in flash. + * \param[in] ui32ByteCount + * The number of bytes to erase. + * + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::eraseFlashRange(uint32_t ui32StartAddress, + uint32_t ui32ByteCount) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + char pcPayload[8]; + uint32_t devStatus; + + // + // Initial check + // + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Calculate retry count + // + uint32_t ui32PageCount = ui32ByteCount / SBL_CC2538_PAGE_ERASE_SIZE; + if( ui32ByteCount % SBL_CC2538_PAGE_ERASE_SIZE) ui32PageCount ++; + uint32_t ui32TryCount = (((ui32PageCount * SBL_CC2538_PAGE_ERASE_TIME_MS) / \ + SBL_DEFAULT_READ_TIMEOUT) + 1); + + // + // Build payload + // - 4B address (MSB first) + // - 4B byte count (MSB first) + // + ulToCharArray(ui32StartAddress, &pcPayload[0]); + ulToCharArray(ui32ByteCount, &pcPayload[4]); + + // + // Set progress + // + setProgress(0); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_ERASE, pcPayload, 8)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, ui32TryCount)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Check device status (Flash failed if page(s) locked) + // + readStatus(&devStatus); + if(devStatus != SblDeviceCC2538::CMD_RET_SUCCESS) + { + setState(SBL_ERROR, "Flash erase failed. (Status 0x%02X = '%s'). Flash pages may be locked.\n", devStatus, getCmdStatusString(devStatus).c_str()); + return SBL_ERROR; + } + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads \e ui32UnitCount (32 bit) words of data from + * device. Destination array is 32 bit wide. The start address must be 4 + * byte aligned. + * + * \param[in] ui32StartAddress + * Start address in device (must be 4 byte aligned). + * \param[in] ui32UnitCount + * Number of data words to read. + * \param[out] pcData + * Pointer to where read data is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::readMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, + uint32_t *pui32Data) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if((ui32StartAddress & 0x03)) + { + setState(SBL_ARGUMENT_ERROR, "readMemory32(): Start address (0x%08X) must be a multiple of 4.\n", ui32StartAddress); + return SBL_ARGUMENT_ERROR; + } + + // + // Set progress + // + setProgress(0); + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + char pcPayload[5]; + uint32_t recvCount = 0; + for(uint32_t i = 0; i < ui32UnitCount; i++) + { + // + // Build payload + // - 4B address (MSB first) + // - 1B access width + // + ulToCharArray((ui32StartAddress + (i*4)), &pcPayload[0]); + pcPayload[4] = SBL_CC2538_ACCESS_WIDTH_4B; + + // + // Set progress + // + setProgress( ((100 * i)/ui32UnitCount) ); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_MEMORY_READ, pcPayload, 5)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive 4B response + // + recvCount = 4; + if((retCode = getResponseData(pcPayload, recvCount)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + if(recvCount != 4) + { + // + // Respond with NAK + // + sendCmdResponse(false); + setState(SBL_ERROR, "Didn't receive 4 B.\n"); + return SBL_ERROR; + } + pui32Data[i] = charArrayToUL(pcPayload); + + // + // Respond with ACK + // + sendCmdResponse(true); + } + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads \e unitCount bytes of data from device. + * Destination array is 8 bit wide. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32UnitCount + * Number of bytes to read. + * \param[out] pcData + * Pointer to where read data is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::readMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, + char *pcData) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Using 4B access width. Expanding byte count to include bytes at start + // and end of sequence. + // + uint32_t begCnt = ui32StartAddress % 4; + uint32_t endCnt = (ui32StartAddress + ui32UnitCount) % 4; + if(endCnt) { endCnt = 4 - endCnt; } + uint32_t totByteCnt = begCnt + ui32UnitCount + endCnt; + + + // + // Word align start address + // + ui32StartAddress -= begCnt; + + // + // Create temporary vector with enough space. + // + std::vector tmpBuf (totByteCnt); + + // + // Set progress + // + setProgress(0); + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + char pcPayload[5]; + uint32_t recvCount = 0; + for(uint32_t i = 0; i < totByteCnt/4; i++) + { + // + // Build payload + // - 4B address (MSB first) + // - 1B access width + // + ulToCharArray((ui32StartAddress + (i*4)), &pcPayload[0]); + pcPayload[4] = SBL_CC2538_ACCESS_WIDTH_4B; + + // + // Set progress + // + setProgress( ((100 * i)/(totByteCnt/4)) ); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_MEMORY_READ, pcPayload, 5)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive 4B response + // + recvCount = 4; + if((retCode = getResponseData(pcPayload, recvCount)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + if(recvCount != 4) + { + // + // Respond with NAK + // + sendCmdResponse(false); + setState(SBL_ERROR, "Didn't receive 4 B.\n"); + return SBL_ERROR; + } + byteSwap(pcPayload); + memcpy(&tmpBuf[4*i], pcPayload, 4); + + // + // Respond with ACK + // + sendCmdResponse(true); + } + + // + // Copy wanted data to pcData + // + for(uint32_t i = 0; i < ui32UnitCount; i++) + { + pcData[i] = tmpBuf.at(i + begCnt); + } + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function writes \e unitCount words of data to device SRAM. + * Source array is 32 bit wide. \e ui32StartAddress must be 4 byte + * aligned. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32UnitCount + * Number of data words (32bit) to write. + * \param[in] pui32Data + * Pointer to source data. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::writeMemory32(uint32_t ui32StartAddress, + uint32_t ui32UnitCount, + const uint32_t *pui32Data) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + char pcPayload[9]; + uint32_t recvCount = 0; + uint32_t currAddr; + + // + // Check input arguments + // + if(!addressInRam(ui32StartAddress, ui32UnitCount*4)) + { + setState(SBL_ARGUMENT_ERROR, "writeMemory32(): Address range (0x%08X + %d bytes) is not in device RAM.\n", ui32StartAddress, ui32UnitCount*4); + return SBL_ARGUMENT_ERROR; + } + if((ui32StartAddress & 0x03)) + { + setState(SBL_ARGUMENT_ERROR, "writeMemory32(): Start address (0x%08X) must be a multiple of 4.\n", ui32StartAddress); + return SBL_ARGUMENT_ERROR; + } + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Set progress + // + setProgress(0); + + for(uint32_t i = 0; i < ui32UnitCount; i++) + { + currAddr = ui32StartAddress + (i * 4); + // + // Build payload + // - 4B address (MSB first) + // - 4B data value (MSB first) + // - 1B access width + // + ulToCharArray(currAddr, &pcPayload[0]); + ulToCharArray(pui32Data[i], &pcPayload[4]); + pcPayload[8] = SBL_CC2538_ACCESS_WIDTH_4B; + + // + // Set progress + // + setProgress( ((100 * i)/ui32UnitCount) ); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_MEMORY_WRITE, pcPayload, 9)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 5)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Device NAKed read command for address 0x%08X.\n", currAddr); + return SBL_ERROR; + } + } + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function writes \e unitCount words of data to device SRAM. + * Source array is 8 bit wide. Parameters \e startAddress and \e unitCount + * must be a a multiple of 4. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32UnitCount + * Number of bytes to write. + * \param[in] pcData + * Pointer to source data. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::writeMemory8(uint32_t ui32StartAddress, + uint32_t ui32UnitCount, + const char *pcData) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + char pcPayload[9]; + uint32_t recvCount = 0; + uint32_t currAddr; + + // + // Check input arguments + // + if(!addressInRam(ui32StartAddress, ui32UnitCount)) + { + setState(SBL_ARGUMENT_ERROR, "writeMemory8(): Address range (0x%08X + %d bytes) is not in device RAM.\n", ui32StartAddress, ui32UnitCount*4); + return SBL_ARGUMENT_ERROR; + } + if((ui32StartAddress & 0x03) || (ui32UnitCount & 0x03)) + { + setState(SBL_ARGUMENT_ERROR, "writeMemory8(): Start address (0x%08X) and byte count (%d) must be a multiple of 4.\n", ui32StartAddress, ui32UnitCount); + return SBL_ARGUMENT_ERROR; + } + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Set progress + // + setProgress(0); + + for(uint32_t i = 0; i < ui32UnitCount/4; i++) + { + currAddr = ui32StartAddress + (i * 4); + // + // Build payload + // - 4B address (MSB first) + // - 4B data value (MSB first) + // - 1B access width + // + ulToCharArray(currAddr, &pcPayload[0]); + memcpy(&pcPayload[4], &pcData[(i * 4)], 4); + pcPayload[8] = SBL_CC2538_ACCESS_WIDTH_4B; + + // + // Set progress + // + setProgress( ((100 * i) / (ui32UnitCount / 4)) ); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_MEMORY_WRITE, pcPayload, 9)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 5)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Device NAKed read command for address 0x%08X.\n", currAddr); + return SBL_ERROR; + } + } + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function calculates CRC over \e byteCount bytes on the device, + * starting at address \e startAddress. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32ByteCount + * Number of bytes to calculate CRC32 over. + * \param[out] pui32Crc + * Pointer to where checksum from device is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::calculateCrc32(uint32_t ui32StartAddress, + uint32_t ui32ByteCount, uint32_t *pui32Crc) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + char pcPayload[8]; + uint32_t ui32RecvCount = 0; + + // + // Check input arguments + // + if(!addressInFlash(ui32StartAddress, ui32ByteCount) && + !addressInRam(ui32StartAddress, ui32ByteCount)) + { + setState(SBL_ARGUMENT_ERROR, "Specified address range (0x%08X + %d bytes) is not in device FLASH nor RAM.\n", ui32StartAddress, ui32ByteCount); + return SBL_ARGUMENT_ERROR; + } + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Set progress + // + setProgress(0); + + // + // Build payload + // - 4B address (MSB first) + // - 4B byte count(MSB first) + // + ulToCharArray(ui32StartAddress, &pcPayload[0]); + ulToCharArray(ui32ByteCount, &pcPayload[4]); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_CRC32, pcPayload, 8)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 5)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Device NAKed CRC32 command.\n"); + return SBL_ERROR; + } + + // + // Get data response + // + ui32RecvCount = 4; + if((retCode = getResponseData(pcPayload, ui32RecvCount)) != SBL_SUCCESS) + { + sendCmdResponse(false); + return retCode; + } + *pui32Crc = charArrayToUL(pcPayload); + + // + // Send ACK/NAK to command + // + bool bAck = (ui32RecvCount == 4) ? true : false; + sendCmdResponse(bAck); + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + + +//----------------------------------------------------------------------------- +/** \brief This function writes \e unitCount words of data to device FLASH. + * Source array is 8 bit wide. Parameters \e startAddress and \e unitCount + * must be a a multiple of 4. This function does not erase the flash + * before writing data, this must be done using e.g. eraseFlashRange(). + * + * \param[in] ui32StartAddress + * Start address in device. Must be a multiple of 4. + * \param[in] ui32ByteCount + * Number of bytes to program. Must be a multiple of 4. + * \param[in] pcData + * Pointer to source data. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::writeFlashRange(uint32_t ui32StartAddress, + uint32_t ui32ByteCount, const char *pcData) +{ + DEBUG_PRINT("\n"); + uint32_t devStatus = SblDeviceCC2538::CMD_RET_UNKNOWN_CMD; + uint32_t retCode = SBL_SUCCESS; + uint32_t bytesLeft, dataIdx, bytesInTransfer; + uint32_t transferNumber = 1; + bool bIsRetry = false; + bool bBlToBeDisabled = false; + std::vector pvTransfer; + uint32_t ui32TotChunks = (ui32ByteCount / SBL_CC2538_MAX_BYTES_PER_TRANSFER); + if(ui32ByteCount % SBL_CC2538_MAX_BYTES_PER_TRANSFER) ui32TotChunks++; + uint32_t ui32CurrChunk = 0; + + // + // Calculate BL configuration address (depends on flash size) + // + uint32_t ui32BlCfgAddr = getBootloaderEnableAddress(); + + // + // Calculate BL configuration buffer index + // + uint32_t ui32BlCfgDataIdx = ui32BlCfgAddr - ui32StartAddress; + + // + // Is BL configuration part of buffer? + // + if(ui32BlCfgDataIdx <= ui32ByteCount) + { + if((pcData[ui32BlCfgDataIdx] & SBL_CC2538_BL_CONFIG_ENABLED_BM) == 0) + { + bBlToBeDisabled = true; + setState(SBL_SUCCESS, "Warning: Bootloader will be disabled.\n"); + } + } + + if(bBlToBeDisabled) + { + // + // Split into two transfers + // + pvTransfer.resize(2); + + // + // Main transfer (before lock bit) + // + pvTransfer[0].bExpectAck = true; + pvTransfer[0].startAddr = ui32StartAddress; + pvTransfer[0].byteCount = (ui32BlCfgAddr - ui32StartAddress) & (~0x03); + pvTransfer[0].startOffset = 0; + + // + // The transfer locking the backdoor + // + pvTransfer[1].bExpectAck = false; + pvTransfer[1].startAddr = ui32BlCfgAddr - (ui32BlCfgAddr % 4); + pvTransfer[1].byteCount = ui32ByteCount - pvTransfer[0].byteCount; + pvTransfer[1].startOffset = ui32BlCfgDataIdx - (ui32BlCfgDataIdx % 4); + + } + else + { + pvTransfer.resize(1); + pvTransfer[0].bExpectAck = true; + pvTransfer[0].byteCount = ui32ByteCount; + pvTransfer[0].startAddr = ui32StartAddress; + pvTransfer[0].startOffset = 0; + } + + // + // For each transfer + // + for(uint32_t i = 0; i < pvTransfer.size(); i++) + { + // + // Sanity check + // + if(pvTransfer[i].byteCount == 0) + { + continue; + } + + // + // Set progress + // + //setProgress(addressToPage(pvTransfer[i].startAddr)); + + // + // Send download command + // + if((retCode = cmdDownload(pvTransfer[i].startAddr, + pvTransfer[i].byteCount)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Check status after download command + // + retCode = readStatus(&devStatus); + if(retCode != SBL_SUCCESS) + { + setState(retCode, "Error during download initialization. Failed to read device status after sending download command.\n"); + return retCode; + } + if(devStatus != SblDeviceCC2538::CMD_RET_SUCCESS) + { + setState(SBL_ERROR, "Error during download initialization. Device returned status %d (%s).\n", devStatus, getCmdStatusString(devStatus).c_str()); + return SBL_ERROR; + } + + // + // Send data in chunks + // + bytesLeft = pvTransfer[i].byteCount; + dataIdx = pvTransfer[i].startOffset; + while(bytesLeft) + { + // + // Set progress + // + //setProgress(addressToPage(ui32StartAddress + dataIdx)); + setProgress( ((100*(++ui32CurrChunk))/ui32TotChunks) ); + + // + // Limit transfer count + // +#if 0 + bytesInTransfer = min(SBL_CC2538_MAX_BYTES_PER_TRANSFER, bytesLeft); +#else + if(bytesLeft > SBL_CC2538_MAX_BYTES_PER_TRANSFER) + { + bytesInTransfer = SBL_CC2538_MAX_BYTES_PER_TRANSFER; + } else { + bytesInTransfer = bytesLeft; + } +#endif + + // + // Send Data command + // + if(retCode = cmdSendData(&pcData[dataIdx], bytesInTransfer) != SBL_SUCCESS) + { + setState(retCode, "Error during flash download. \n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d.\n", + (ui32StartAddress+dataIdx), + addressToPage(ui32StartAddress+dataIdx), + bytesInTransfer, + (transferNumber)); + return retCode; + } + + if(pvTransfer[i].bExpectAck) + { + // + // Check status after send data command + // + devStatus = 0; + retCode = readStatus(&devStatus); + if(retCode != SBL_SUCCESS) + { + setState(retCode, "Error during flash download. Failed to read device status.\n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d in chunk %d.\n", + (ui32StartAddress+dataIdx), + addressToPage(ui32StartAddress + dataIdx), + (bytesInTransfer), (transferNumber), + (i)); + return retCode; + } + if(devStatus != SblDeviceCC2538::CMD_RET_SUCCESS) + { + setState(SBL_SUCCESS, "Device returned status %s\n", getCmdStatusString(devStatus).c_str()); + if(bIsRetry) + { + // + // We have failed a second time. Aborting. + setState(SBL_ERROR, "Error retrying flash download.\n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d in chunk %d.\n", + (ui32StartAddress+dataIdx), + addressToPage(ui32StartAddress + dataIdx), + (bytesInTransfer), (transferNumber), + (i)); + return SBL_ERROR; + } + + // + // Retry to send data one more time. + // + bIsRetry = true; + continue; + } + } + else + { + // + // We're locking device and will lose access + // + m_bCommInitialized = false; + + } + + // + // Update index and bytesLeft + // + bytesLeft -= bytesInTransfer; + dataIdx += bytesInTransfer; + transferNumber++; + bIsRetry = false; + } + } + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function sends the specified bootloader command. + * + * \param[in] ui32Cmd + * The command to send. + * \param[in] pcSendData + * Pointer to the data to send with the command. + * \param[in] ui32SendLen + * The number of bytes to send from \e pcSendData. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::sendCmd(uint32_t ui32Cmd, const char *pcSendData/* = NULL*/, + uint32_t ui32SendLen/* = 0*/) +{ + DEBUG_PRINT("\n"); + unsigned char pktLen = ui32SendLen + 3; // +3 => <1b Length>, <1B checksum>, <1B cmd> + std::vector pvPkt((pktLen)); + unsigned char pktSum = generateCheckSum(ui32Cmd, pcSendData, ui32SendLen); + + // + // Build packet + // + pvPkt.at(0) = pktLen; + pvPkt.at(1) = pktSum; + pvPkt.at(2) = (unsigned char)ui32Cmd; + if(ui32SendLen) + { + memcpy(&pvPkt[3], pcSendData, ui32SendLen); + } + + // + // Send packet + // + if(m_pCom->writeBytes(&pvPkt[0], pvPkt.size()) < 1) + { + setState(SBL_PORT_ERROR, "Writing to device failed (Command '%s').\n", getCmdString(ui32Cmd).c_str()); + return SBL_PORT_ERROR; + } + + + // + // Empty and deallocate vector + // + pvPkt.clear(); + std::vector().swap(pvPkt); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function initializes connection to the CC2538 device. + * + * \param[in] bSetXosc + * If true, try to enable device XOSC. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::initCommunication(bool bSetXosc) +{ + DEBUG_PRINT("\n"); + bool bSuccess, bBaudSetOk; + int retCode = SBL_ERROR; + + // + // Send dummy command to see if device is already initialized at + // this baud rate. + // + if(sendCmd(0) != SBL_SUCCESS) + { + return SBL_ERROR; + } + + // + // Do we get a response (ACK/NAK)? + // + bSuccess = false; + if(getCmdResponse(bSuccess, SBL_DEFAULT_RETRY_COUNT, true) != SBL_SUCCESS) + { + // + // No response received. Try auto baud + // + if(retCode = sendAutoBaud(bBaudSetOk) != SBL_SUCCESS) + { + return retCode; + } + } + + if(bSetXosc) + { + setState(SBL_SUCCESS, "Trying to set device XOSC.\n"); + // + // Try to enable XOSC + // + if((retCode = setXosc()) != SBL_SUCCESS) + { + // + // setXosc returned error + // + setState(retCode, "Failed to activate device XOSC.\n"); + return retCode; + } + + // + // Send dummy command + // + bSuccess = false; + sendCmd(0); + if(retCode = getCmdResponse(bSuccess, SBL_DEFAULT_RETRY_COUNT, true) != SBL_SUCCESS) + { + // + // Send auto baud again + // + if((retCode = sendAutoBaud(bBaudSetOk)) != SBL_SUCCESS) + { + setState((tSblStatus)retCode, "Auto baud detection failed after starting XOSC.\n"); + return retCode; + } + setState(SBL_SUCCESS, "Device XOSC activated.\n"); + } + } + + m_bCommInitialized = true; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function returns a string representation of the \e ui32Cmd + * command. + * + * \param[out] ui32Cmd + * The serial bootloader command. + * \return + * Returns std::string with name of device command. + */ +//----------------------------------------------------------------------------- +std::string +SblDeviceCC2538::getCmdString(uint32_t ui32Cmd) +{ + DEBUG_PRINT("\n"); + switch(ui32Cmd) + { + case SblDeviceCC2538::CMD_PING: return "CMD_PING"; break; + case SblDeviceCC2538::CMD_CRC32: return "CMD_CRC32"; break; + case SblDeviceCC2538::CMD_DOWNLOAD: return "CMD_DOWNLOAD"; break; + case SblDeviceCC2538::CMD_ERASE: return "CMD_ERASE"; break; + case SblDeviceCC2538::CMD_GET_CHIP_ID: return "CMD_GET_CHIP_ID"; break; + case SblDeviceCC2538::CMD_GET_STATUS: return "CMD_GET_STATUS"; break; + case SblDeviceCC2538::CMD_MEMORY_READ: return "CMD_MEMORY_READ"; break; + case SblDeviceCC2538::CMD_MEMORY_WRITE: return "CMD_MEMORY_WRITE"; break; + case SblDeviceCC2538::CMD_RESET: return "CMD_RESET"; break; + default: return "Unknown command"; break; + } +} + + +//----------------------------------------------------------------------------- +/** \brief This function returns a string representation of the + * \e ui32Status serial bootloader status value. + * + * \param[out] ui32Status + * The serial bootloader status value. + * \return + * Returns std::string of device status. + */ +//----------------------------------------------------------------------------- +std::string +SblDeviceCC2538::getCmdStatusString(uint32_t ui32Status) +{ + DEBUG_PRINT("\n"); + switch(ui32Status) + { + case SblDeviceCC2538::CMD_RET_FLASH_FAIL: return "FLASH_FAIL"; break; + case SblDeviceCC2538::CMD_RET_INVALID_ADR: return "INVALID_ADR"; break; + case SblDeviceCC2538::CMD_RET_INVALID_CMD: return "INVALID_CMD"; break; + case SblDeviceCC2538::CMD_RET_SUCCESS: return "SUCCESS"; break; + case SblDeviceCC2538::CMD_RET_UNKNOWN_CMD: return "UNKNOWN_CMD"; break; + default: return "Unknown status"; break; + } +} + + +//----------------------------------------------------------------------------- +/** \brief This function sends the CC2538 download command and handles the + * device response. \e ui32ByteCount must be a multiple of 4. + * + * \param[in] ui32Address + * The start address in CC2538 flash. + * \param[in] ui32ByteCount + * The total number of bytes to program on the device. + * + * \return + * Returns SBL_SUCCESS if command and response was successful. + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::cmdDownload(uint32_t ui32Address, uint32_t ui32Size) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + + // + // Check input arguments + // + if(!addressInFlash(ui32Address, ui32Size)) + { + setState(SBL_ARGUMENT_ERROR, "Flash download: Address range (0x%08X + %d bytes) is not in device FLASH nor RAM.\n", ui32Address, ui32Size); + return SBL_ARGUMENT_ERROR; + } + if(ui32Size & 0x03) + { + setState(SBL_ARGUMENT_ERROR, "Flash download: Byte count must be a multiple of 4\n"); + return SBL_ARGUMENT_ERROR; + } + + // + // Generate payload + // - 4B Program address + // - 4B Program size + // + char pcPayload[8]; + ulToCharArray(ui32Address, &pcPayload[0]); + ulToCharArray(ui32Size, &pcPayload[4]); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_DOWNLOAD, pcPayload, 8)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Return command response + // + return (bSuccess) ? SBL_SUCCESS : SBL_ERROR; +} + + +//----------------------------------------------------------------------------- +/** \brief This function sends the CC2538 SendData command and handles the + * device response. \e ui32ByteCount is limited by + * SBL_CC2538_MAX_BYTES_PER_TRANSFER. + * + * \param[in] pcData + * Pointer to the data to send. + * \param[in] ui32ByteCount + * The number of bytes to send. + * + * \return + * Returns SBL_SUCCESS if command and response was successful. + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::cmdSendData(const char *pcData, uint32_t ui32ByteCount) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if(ui32ByteCount > SBL_CC2538_MAX_BYTES_PER_TRANSFER) + { + setState(SBL_ERROR, "Error: Byte count (%d) exceeds maximum transfer size %d.\n", ui32ByteCount, SBL_CC2538_MAX_BYTES_PER_TRANSFER); + return SBL_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_SEND_DATA, pcData, ui32ByteCount)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 3)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function returns the FLASH address of the bootloader enable +* configuration. +* +* \return +* Returns true if the address/range is within the device RAM. +*/ +//----------------------------------------------------------------------------- +uint32_t SblDeviceCC2538::getBootloaderEnableAddress() +{ + DEBUG_PRINT("\n"); + return (SBL_CC2538_FLASH_START_ADDRESS + getFlashSize() - getPageEraseSize() + SBL_CC2538_BL_CONFIG_PAGE_OFFSET); +} + +//----------------------------------------------------------------------------- +/** \brief This function sends the CC2538 SetXosc command and handles the + * response from the device. + * + * \return + * Returns SBL_SUCCESS if command and response was successful. + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::setXosc() +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2538::CMD_SET_XOSC)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 5, true)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function returns the address within which the specified + * \e ui32Address is located. + * + * \return + * Returns the flash page within which an address is located. + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2538::addressToPage(uint32_t ui32Address) +{ + DEBUG_PRINT("\n"); + return ((ui32Address - SBL_CC2538_FLASH_START_ADDRESS) / \ + SBL_CC2538_PAGE_ERASE_SIZE); +} + + +//----------------------------------------------------------------------------- +/** \brief This function checks if the specified \e ui32StartAddress (or range) + * is located within the device RAM area. + * + * \return + * Returns true if the address/range is within the device RAM. + */ +//----------------------------------------------------------------------------- +bool +SblDeviceCC2538::addressInRam(uint32_t ui32StartAddress, + uint32_t ui32ByteCount/* = 1*/) +{ + DEBUG_PRINT("\n"); + uint32_t ui32EndAddr = ui32StartAddress + ui32ByteCount; + + if(ui32StartAddress < SBL_CC2538_RAM_START_ADDRESS) + { + return false; + } + if(ui32EndAddr > (SBL_CC2538_RAM_START_ADDRESS + getRamSize())) + { + return false; + } + return true; +} + + +//----------------------------------------------------------------------------- +/** \brief This function checks if the specified \e ui32StartAddress (or range) + * is located within the device FLASH area. + * + * \return + * Returns true if the address/range is within the device FLASH. + */ +//----------------------------------------------------------------------------- +bool +SblDeviceCC2538::addressInFlash(uint32_t ui32StartAddress, + uint32_t ui32ByteCount/* = 1*/) +{ + DEBUG_PRINT("\n"); + uint32_t ui32EndAddr = ui32StartAddress + ui32ByteCount; + + if(ui32StartAddress < SBL_CC2538_FLASH_START_ADDRESS) + { + return false; + } + if(ui32EndAddr > (SBL_CC2538_FLASH_START_ADDRESS + getFlashSize())) + { + return false; + } + + return true; +} diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2538.h b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2538.h new file mode 100755 index 000000000..c5316c621 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2538.h @@ -0,0 +1,126 @@ +#ifndef __SBL_DEVICE_CC2538_H__ +#define __SBL_DEVICE_CC2538_H__ +/****************************************************************************** +* Filename: sbl_device_cc2538.h +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader for CC2538 header file. +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ +#include + +// +// For more information about the CC2538 serial bootloader interface, +// please refer to the CC2538 ROM User's guide (http://www.ti.com/lit/swru333) +// + +#define SBL_CC2538_PAGE_ERASE_SIZE 2048 +#define SBL_CC2538_FLASH_START_ADDRESS 0x00200000 +#define SBL_CC2538_RAM_START_ADDRESS 0x20000000 +#define SBL_CC2538_ACCESS_WIDTH_4B 4 +#define SBL_CC2538_ACCESS_WIDTH_1B 1 +#define SBL_CC2538_PAGE_ERASE_TIME_MS 20 +#define SBL_CC2538_MAX_BYTES_PER_TRANSFER 252 +#define SBL_CC2538_DIECFG0 0x400D3014 +#define SBL_CC2538_BL_CONFIG_PAGE_OFFSET 2007 +#define SBL_CC2538_BL_CONFIG_ENABLED_BM 0x10 + +class SblDeviceCC2538 : public SblDevice +{ +public: + SblDeviceCC2538(); // Constructor + ~SblDeviceCC2538(); // Destructor + + enum { + CMD_PING = 0x20, + CMD_DOWNLOAD = 0x21, + CMD_RUN = 0x22, + CMD_GET_STATUS = 0x23, + CMD_SEND_DATA = 0x24, + CMD_RESET = 0x25, + CMD_ERASE = 0x26, + CMD_CRC32 = 0x27, + CMD_GET_CHIP_ID = 0x28, + CMD_SET_XOSC = 0x29, + CMD_MEMORY_READ = 0x2A, + CMD_MEMORY_WRITE = 0x2B, + }; + + enum { + CMD_RET_SUCCESS = 0x40, + CMD_RET_UNKNOWN_CMD = 0x41, + CMD_RET_INVALID_CMD = 0x42, + CMD_RET_INVALID_ADR = 0x43, + CMD_RET_FLASH_FAIL = 0x44, + }; + +protected: + + // Virtual functions from SblDevice + uint32_t ping(); + + uint32_t readStatus(uint32_t *pui32Status); + uint32_t readDeviceId(uint32_t *pui32DeviceId); + uint32_t readFlashSize(uint32_t *pui32FlashSize); + uint32_t readRamSize(uint32_t *pui32RamSize); + + uint32_t run(uint32_t ui32Address); + uint32_t reset(); + uint32_t eraseFlashRange(uint32_t ui32StartAddress, uint32_t ui32ByteCount); + uint32_t writeFlashRange(uint32_t ui32StartAddress, uint32_t ui32ByteCount, const char *pcData); + uint32_t readMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, uint32_t *pui32Data); + uint32_t readMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, char *pcData); + uint32_t writeMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, const uint32_t *pui32Data); + uint32_t writeMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, const char *pcData); + + uint32_t calculateCrc32(uint32_t ui32StartAddress, uint32_t ui32ByteCount, uint32_t *pui32Crc); + + uint32_t sendCmd(uint32_t ui32Cmd, const char *pcSendData = NULL, uint32_t ui32SendLen = 0); + uint32_t addressToPage(uint32_t ui32Address); + bool addressInRam(uint32_t ui32StartAddress, uint32_t ui32ByteCount = 1); + bool addressInFlash(uint32_t ui32StartAddress, uint32_t ui32ByteCount = 1); + uint32_t setXosc(); + +private: + uint32_t initCommunication(bool bSetXosc); + uint32_t cmdDownload(uint32_t ui32Address, uint32_t ui32Size); + uint32_t cmdSendData(const char *pcData, uint32_t ui32ByteCount); + + uint32_t getBootloaderEnableAddress(); + + std::string getCmdString(uint32_t ui32Cmd); + std::string getCmdStatusString(uint32_t ui32Status); +}; + +#endif // __SBL_DEVICE_CC2538_H__ diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2650.cpp b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2650.cpp new file mode 100755 index 000000000..e2012144f --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2650.cpp @@ -0,0 +1,1903 @@ +/****************************************************************************** +* Filename: sbl_device_cc2650.cpp +* Revised: $Date: 2013-08-21 14:33:34 +0200 (on, 21 aug 2013) $ +* Revision: $Revision: 27319 $ +* +* Description: Serial Bootloader device file for CC2650 +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include +#include "sbl_device.h" +#include "sbl_device_cc2650.h" + +#include "serialib.h" + +#include + +#if 1 +static uint32_t min(uint32_t a, uint32_t b) +{ + if(a > b) + { + return b; + } + return a; +} +#endif + +/// Struct used when splitting long transfers +typedef struct { + uint32_t startAddr; + uint32_t byteCount; + uint32_t startOffset; + bool bExpectAck; +} tTransfer; + +static uint32_t getDeviceRev(uint32_t deviceId) +{ + uint32_t tmp = deviceId >> 28; + switch(tmp) + { + // Early samples (Rev 1) + case 0: + case 1: + return 1; + default: + return 2; + } +} + + +//----------------------------------------------------------------------------- +/** \brief Constructor + */ +//----------------------------------------------------------------------------- +SblDeviceCC2650::SblDeviceCC2650() +{ + m_deviceRev = 0; + m_pageEraseSize = SBL_CC2650_PAGE_ERASE_SIZE; + + if(!m_pCom) + { + m_pCom = new serialib(); + } +} + +//----------------------------------------------------------------------------- +/** \brief Destructor + */ +//----------------------------------------------------------------------------- +SblDeviceCC2650::~SblDeviceCC2650() +{ +} + +//----------------------------------------------------------------------------- +/** \brief This function sends ping command to device. + * + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::ping() +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bResponse = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_PING)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Get response + // + if((retCode = getCmdResponse(bResponse)) != SBL_SUCCESS) + { + return retCode; + } + + return (bResponse) ? SBL_SUCCESS : SBL_ERROR; +} + + +//----------------------------------------------------------------------------- +/** \brief This function gets status from device. + * + * \param[out] pStatus + * Pointer to where status is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::readStatus(uint32_t *pui32Status) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_GET_STATUS)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive command response data + // + char status = 0; + uint32_t ui32NumBytes = 1; + if((retCode = getResponseData(&status, ui32NumBytes)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + + // + // Respond with ACK + // + sendCmdResponse(true); + + m_lastDeviceStatus = status; + *pui32Status = status; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads device ID. + * + * \param[out] pui32DeviceId + * Pointer to where device ID is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::readDeviceId(uint32_t *pui32DeviceId) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_GET_CHIP_ID)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive response data + // + char pId[4]; + memset(pId, 0, 4); + uint32_t numBytes = 4; + if((retCode = getResponseData(pId, numBytes)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + + if(numBytes != 4) + { + // + // Respond with NAK + // + sendCmdResponse(false); + setState(SBL_ERROR, "Didn't receive 4 B.\n"); + return SBL_ERROR; + } + + // + // Respond with ACK + // + sendCmdResponse(true); + + // + // Store retrieved ID and report success + // + *pui32DeviceId = charArrayToUL(pId); + m_deviceId = *pui32DeviceId; + + // + // Store device revision (used internally, see sbl_device_cc2650.h) + // + m_deviceRev = getDeviceRev(m_deviceId); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads device FLASH size in bytes. + * + * \param[out] pui32FlashSize + * Pointer to where FLASH size is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::readFlashSize(uint32_t *pui32FlashSize) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + + // + // Read CC2650 DIECFG0 (contains FLASH size information) + // + uint32_t addr = SBL_CC2650_FLASH_SIZE_CFG; + uint32_t value; + if((retCode = readMemory32(addr, 1, &value)) != SBL_SUCCESS) + { + setState((tSblStatus)retCode, "Failed to read device FLASH size: %s", getLastError().c_str()); + return retCode; + } + // + // Calculate flash size (The number of flash sectors are at bits [7:0]) + // + value &= 0xFF; + *pui32FlashSize = value * getPageEraseSize(); + + m_flashSize = *pui32FlashSize; + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads device RAM size in bytes. + * + * \param[out] pui32RamSize + * Pointer to where RAM size is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::readRamSize(uint32_t *pui32RamSize) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + + // + // Read CC2650 DIECFG0 (contains RAM size information + // + uint32_t addr = SBL_CC2650_RAM_SIZE_CFG; + uint32_t value; + if((retCode = readMemory32(addr, 1, &value)) != SBL_SUCCESS) + { + setState(retCode, "Failed to read device RAM size: %s", getLastError().c_str()); + return retCode; + } + + // + // Calculate RAM size in bytes (Ram size bits are at bits [1:0]) + // + value &= 0x03; + if(m_deviceRev == 1) + { + // Early samples has less RAM + switch(value) + { + case 3: *pui32RamSize = 0x4000; break; // 16 KB + case 2: *pui32RamSize = 0x2000; break; // 8 KB + case 1: *pui32RamSize = 0x1000; break; // 4 KB + case 0: // 2 KB + default:*pui32RamSize = 0x0800; break; // All invalid values are interpreted as 2 KB + } + } + else + { + switch(value) + { + case 3: *pui32RamSize = 0x5000; break; // 20 KB + case 2: *pui32RamSize = 0x4000; break; // 16 KB + case 1: *pui32RamSize = 0x2800; break; // 10 KB + case 0: // 4 KB + default:*pui32RamSize = 0x1000; break; // All invalid values are interpreted as 4 KB + } + } + + // CC1310F64 and CC1310F32 officially has 16KB SRAM, but 20KB enabled. Return official value. + if((sm_chipType == 0x1310 && m_deviceRev > 1) && + (m_flashSize == (64*1024) || (m_flashSize == (32*1024)))) { + *pui32RamSize = 0x4000; + } + + // + // Save RAM size internally + // + m_ramSize = *pui32RamSize; + + return retCode; +} + +//----------------------------------------------------------------------------- +/** \brief This function reset the device. Communication to the device must be + * reinitialized after calling this function. + * + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::reset() +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_RESET)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Reset command NAKed by device.\n"); + return SBL_ERROR; + } + + m_bCommInitialized = false; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function erases device flash pages. Starting page is the page + * that includes the address in \e startAddress. Ending page is the page + * that includes the address . CC13/CC26xx erase + * size is 4KB. + * + * \param[in] ui32StartAddress + * The start address in flash. + * \param[in] ui32ByteCount + * The number of bytes to erase. + * + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::eraseFlashRange(uint32_t ui32StartAddress, + uint32_t ui32ByteCount) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + char pcPayload[4]; + uint32_t devStatus; + + // + // Initial check + // + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Calculate retry count + // + uint32_t ui32PageCount = ui32ByteCount / getPageEraseSize(); + if( ui32ByteCount % getPageEraseSize()) ui32PageCount ++; + setProgress( 0 ); + for(uint32_t i = 0; i < ui32PageCount; i++) + { + + // + // Build payload + // - 4B address (MSB first) + // + ulToCharArray(ui32StartAddress + i * getPageEraseSize(), &pcPayload[0]); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_SECTOR_ERASE, pcPayload, 4)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Check device status (Flash failed if page(s) locked) + // + readStatus(&devStatus); + if(devStatus != SblDeviceCC2650::CMD_RET_SUCCESS) + { + setState(SBL_ERROR, "Flash erase failed. (Status 0x%02X = '%s'). Flash pages may be locked.\n", devStatus, getCmdStatusString(devStatus).c_str()); + return SBL_ERROR; + } + + setProgress( 100*(i+1)/ui32PageCount ); + } + + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads \e ui32UnitCount (32 bit) words of data from + * device. Destination array is 32 bit wide. The start address must be 4 + * byte aligned. + * + * \param[in] ui32StartAddress + * Start address in device (must be 4 byte aligned). + * \param[in] ui32UnitCount + * Number of data words to read. + * \param[out] pcData + * Pointer to where read data is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::readMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, + uint32_t *pui32Data) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if((ui32StartAddress & 0x03)) + { + setState(SBL_ARGUMENT_ERROR, "readMemory32(): Start address (0x%08X) must be a multiple of 4.\n", ui32StartAddress); + return SBL_ARGUMENT_ERROR; + } + + // + // Set progress + // + setProgress(0); + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + unsigned char pcPayload[6]; + uint32_t responseData[SBL_CC2650_MAX_MEMREAD_WORDS]; + uint32_t chunkCount = ui32UnitCount / SBL_CC2650_MAX_MEMREAD_WORDS; + if(ui32UnitCount % SBL_CC2650_MAX_MEMREAD_WORDS) chunkCount++; + uint32_t remainingCount = ui32UnitCount; + + for(uint32_t i = 0; i < chunkCount; i++) + { + uint32_t dataOffset = (i * SBL_CC2650_MAX_MEMREAD_WORDS); + uint32_t chunkStart = ui32StartAddress + dataOffset; +#if 1 + uint32_t chunkSize = min(remainingCount, SBL_CC2650_MAX_MEMREAD_WORDS); +#else + uint32_t chunkSize; + if(remainingCount > SBL_CC2650_MAX_MEMREAD_WORDS) + { + chunkSize = SBL_CC2650_MAX_MEMREAD_WORDS; + } else { + chunkSize = remainingCount; + } +#endif + remainingCount -= chunkSize; + + // + // Build payload + // - 4B address (MSB first) + // - 1B access width + // - 1B Number of accesses (in words) + // + ulToCharArray(chunkStart, (char *)&pcPayload[0]); + pcPayload[4] = SBL_CC2650_ACCESS_WIDTH_32B; + pcPayload[5] = chunkSize; + // + // Set progress + // + setProgress(((i * 100) / chunkCount)); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_MEMORY_READ, (char *)pcPayload, 6)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive 4B response + // + uint32_t expectedBytes = chunkSize * 4; + uint32_t recvBytes = expectedBytes; + if((retCode = getResponseData((char*)responseData, recvBytes)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + + if(recvBytes != expectedBytes) + { + // + // Respond with NAK + // + sendCmdResponse(false); + setState(SBL_ERROR, "Didn't receive 4 B.\n"); + return SBL_ERROR; + } + + memcpy(&pui32Data[dataOffset], responseData, expectedBytes); + //delete [] responseData; + // + // Respond with ACK + // + sendCmdResponse(true); + } + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function reads \e unitCount bytes of data from device. + * Destination array is 8 bit wide. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32UnitCount + * Number of bytes to read. + * \param[out] pcData + * Pointer to where read data is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::readMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, + char *pcData) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if(ui32UnitCount == 0) + { + setState(SBL_ARGUMENT_ERROR, "readMemory8(): Read count is zero. Must be at least 1.\n"); + return SBL_ARGUMENT_ERROR; + } + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + unsigned char pcPayload[6]; + uint32_t chunkCount = ui32UnitCount / SBL_CC2650_MAX_MEMREAD_BYTES; + if(ui32UnitCount % SBL_CC2650_MAX_MEMREAD_BYTES) chunkCount++; + uint32_t remainingCount = ui32UnitCount; + + for(uint32_t i = 0; i < chunkCount; i++) + { + uint32_t dataOffset = (i * SBL_CC2650_MAX_MEMREAD_BYTES); + uint32_t chunkStart = ui32StartAddress + dataOffset; + uint32_t chunkSize = min(remainingCount, SBL_CC2650_MAX_MEMREAD_BYTES); + remainingCount -= chunkSize; + + // + // Build payload + // - 4B address (MSB first) + // - 1B access width + // - 1B number of accesses (in bytes) + // + ulToCharArray(chunkStart, (char *)&pcPayload[0]); + pcPayload[4] = SBL_CC2650_ACCESS_WIDTH_8B; + pcPayload[5] = chunkSize; + + // + // Set progress + // + setProgress( ((i*100) / chunkCount)); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_MEMORY_READ, (char *)pcPayload, 6)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + // + // Receive response + // + uint32_t expectedBytes = chunkSize; + if((retCode = getResponseData(&pcData[dataOffset], chunkSize)) != SBL_SUCCESS) + { + // + // Respond with NAK + // + sendCmdResponse(false); + return retCode; + } + + if(chunkSize != expectedBytes) + { + // + // Respond with NAK + // + sendCmdResponse(false); + setState(SBL_ERROR, "readMemory8(): Received %d bytes (%d B expected) in iteration %d.\n", chunkSize, expectedBytes, i); + return SBL_ERROR; + } + + // + // Respond with ACK + // + sendCmdResponse(true); + } + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + + +//----------------------------------------------------------------------------- +/** \brief This function writes \e unitCount words of data to device SRAM. + * Max 61 32-bit words supported. Source array is 32 bit wide. + * \e ui32StartAddress must be 4 byte aligned. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32UnitCount + * Number of data words (32bit) to write. + * \param[in] pui32Data + * Pointer to source data. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::writeMemory32(uint32_t ui32StartAddress, + uint32_t ui32UnitCount, + const uint32_t *pui32Data) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if((ui32StartAddress & 0x03)) + { + setState(SBL_ARGUMENT_ERROR, "writeMemory32(): Start address (0x%08X) must 4 byte aligned.\n", ui32StartAddress); + return SBL_ARGUMENT_ERROR; + } + if(addressInBLWorkMemory(ui32StartAddress, ui32UnitCount * 4)) + { + // Issue warning + setState(SBL_ARGUMENT_ERROR, "writeMemory32(): Writing to bootloader work memory/stack:\n(0x%08X-0x%08X, 0x%08X-0x%08X)\n", + SBL_CC2650_BL_WORK_MEMORY_START,SBL_CC2650_BL_WORK_MEMORY_END, SBL_CC2650_BL_STACK_MEMORY_START,SBL_CC2650_BL_STACK_MEMORY_END); + return SBL_ARGUMENT_ERROR; + } + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + uint32_t chunkCount = (ui32UnitCount / SBL_CC2650_MAX_MEMWRITE_WORDS); + if(ui32UnitCount % SBL_CC2650_MAX_MEMWRITE_WORDS) chunkCount++; + uint32_t remainingCount = ui32UnitCount; + char* pcPayload = new char[5 + (SBL_CC2650_MAX_MEMWRITE_WORDS*4)]; + + for(uint32_t i = 0; i < chunkCount; i++) + { + uint32_t chunkOffset = i * SBL_CC2650_MAX_MEMWRITE_WORDS; + uint32_t chunkStart = ui32StartAddress + (chunkOffset * 4); + uint32_t chunkSize = min(remainingCount, SBL_CC2650_MAX_MEMWRITE_WORDS); + remainingCount -= chunkSize; + + // + // Build payload + // - 4B address (MSB first) + // - 1B access width + // - 1-SBL_CC2650_MAX_MEMWRITE_WORDS data (MSB first) + // + ulToCharArray(chunkStart, &pcPayload[0]); + pcPayload[4] = SBL_CC2650_ACCESS_WIDTH_32B; + for(uint32_t j = 0; j < chunkSize; j++) + { + ulToCharArray(pui32Data[j + chunkOffset], &pcPayload[5 + j*4]); + } + + // + // Set progress + // + setProgress( ((i * 100) / chunkCount) ); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_MEMORY_WRITE, pcPayload, 5 + chunkSize*4)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 5)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "writeMemory32(): Device NAKed command for address 0x%08X.\n", chunkStart); + return SBL_ERROR; + } + } + + // + // Set progress + // + setProgress(100); + + // + // Cleanup + // + delete [] pcPayload; + + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Write \e unitCount words of data to device SRAM. Source array is + * 8 bit wide. Max 244 bytes of data. Source array is 32 bit wide. + * Parameters \e startAddress and \e unitCount must be a a multiple of 4. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32UnitCount + * Number of bytes to write. + * \param[in] pcData + * Pointer to source data. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::writeMemory8(uint32_t ui32StartAddress, + uint32_t ui32UnitCount, + const char *pcData) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if(addressInBLWorkMemory(ui32StartAddress, ui32UnitCount)) + { + // Issue warning + setState(SBL_ARGUMENT_ERROR, "writeMemory8(): Writing to bootloader work memory/stack:\n(0x%08X-0x%08X, 0x%08X-0x%08X)\n", + SBL_CC2650_BL_WORK_MEMORY_START,SBL_CC2650_BL_WORK_MEMORY_END, SBL_CC2650_BL_STACK_MEMORY_START,SBL_CC2650_BL_STACK_MEMORY_END); + return SBL_ARGUMENT_ERROR; + } + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + uint32_t chunkCount = (ui32UnitCount / SBL_CC2650_MAX_MEMWRITE_BYTES); + if(ui32UnitCount % SBL_CC2650_MAX_MEMWRITE_BYTES) chunkCount++; + uint32_t remainingCount = ui32UnitCount; + char* pcPayload = new char[5 + SBL_CC2650_MAX_MEMWRITE_BYTES]; + + for(uint32_t i = 0; i < chunkCount; i++) + { + uint32_t chunkOffset = i * SBL_CC2650_MAX_MEMWRITE_BYTES; + uint32_t chunkStart = ui32StartAddress + chunkOffset; + uint32_t chunkSize = min(remainingCount, SBL_CC2650_MAX_MEMWRITE_BYTES); + remainingCount -= chunkSize; + + // + // Build payload + // - 4B address (MSB first) + // - 1B access width + // - 1-SBL_CC2650_MAX_MEMWRITE_BYTES bytes data + // + ulToCharArray(chunkStart, &pcPayload[0]); + pcPayload[4] = SBL_CC2650_ACCESS_WIDTH_8B; + memcpy(&pcPayload[5], &pcData[chunkOffset], chunkSize); + + // + // Set progress + // + setProgress( ((i * 100) / chunkCount) ); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_MEMORY_WRITE, pcPayload, 5 + chunkSize)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 5)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "writeMemory8(): Device NAKed command for address 0x%08X.\n", chunkStart); + return SBL_ERROR; + } + } + + // + // Set progress + // + setProgress(100); + + // + // Cleanup + // + delete [] pcPayload; + + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Calculate CRC over \e byteCount bytes, starting at address + * \e startAddress. + * + * \param[in] ui32StartAddress + * Start address in device. + * \param[in] ui32ByteCount + * Number of bytes to calculate CRC32 over. + * \param[out] pui32Crc + * Pointer to where checksum from device is stored. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::calculateCrc32(uint32_t ui32StartAddress, + uint32_t ui32ByteCount, uint32_t *pui32Crc) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + char pcPayload[12]; + uint32_t ui32RecvCount = 0; + + // + // Check input arguments + // + if(!addressInFlash(ui32StartAddress, ui32ByteCount) && + !addressInRam(ui32StartAddress, ui32ByteCount)) + { + setState(SBL_ARGUMENT_ERROR, "Specified address range (0x%08X + %d bytes) is not in device FLASH nor RAM.\n", ui32StartAddress, ui32ByteCount); + return SBL_ARGUMENT_ERROR; + } + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Set progress + // + setProgress(0); + + // + // Build payload + // - 4B address (MSB first) + // - 4B byte count(MSB first) + // + ulToCharArray(ui32StartAddress, &pcPayload[0]); + ulToCharArray(ui32ByteCount, &pcPayload[4]); + pcPayload[8] = 0x00; + pcPayload[9] = 0x00; + pcPayload[10] = 0x00; + pcPayload[11] = 0x00; + // + // Send command + // +#if 0 + { + int i; + printf("@@send CMD_CRC32:"); + for(i=0;i<12;i++) printf(" %02x",(unsigned char)pcPayload[i]); + printf("\n"); + } +#endif + if((retCode = sendCmd(SblDeviceCC2650::CMD_CRC32, pcPayload, 12)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 5)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Device NAKed CRC32 command.\n"); + return SBL_ERROR; + } + + // + // Get data response + // + ui32RecvCount = 4; + if((retCode = getResponseData(pcPayload, ui32RecvCount)) != SBL_SUCCESS) + { + sendCmdResponse(false); + return retCode; + } +#if 0 + { + int i; + printf("@@recive CRC:"); + for(i=0;i<4;i++) printf(" %02x",(unsigned char)pcPayload[i]); + printf("\n"); + } +#endif + *pui32Crc = charArrayToUL(pcPayload); + + // + // Send ACK/NAK to command + // + bool bAck = (ui32RecvCount == 4) ? true : false; + sendCmdResponse(bAck); + + // + // Set progress + // + setProgress(100); + + return SBL_SUCCESS; +} + + + +//----------------------------------------------------------------------------- +/** \brief Write \e unitCount words of data to device FLASH. Source array is + * 8 bit wide. Parameters \e startAddress and \e unitCount must be a + * a multiple of 4. This function does not erase the flash before writing + * data, this must be done using e.g. eraseFlashRange(). + * + * \param[in] ui32StartAddress + * Start address in device. Must be a multiple of 4. + * \param[in] ui32ByteCount + * Number of bytes to program. Must be a multiple of 4. + * \param[in] pcData + * Pointer to source data. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::writeFlashRange(uint32_t ui32StartAddress, + uint32_t ui32ByteCount, const char *pcData) +{ + DEBUG_PRINT("\n"); + uint32_t devStatus = SblDeviceCC2650::CMD_RET_UNKNOWN_CMD; + uint32_t retCode = SBL_SUCCESS; + uint32_t bytesLeft, dataIdx, bytesInTransfer; + uint32_t transferNumber = 1; + bool bIsRetry = false; + bool bBlToBeDisabled = false; + std::vector pvTransfer; + uint32_t ui32TotChunks = (ui32ByteCount / SBL_CC2650_MAX_BYTES_PER_TRANSFER); + if(ui32ByteCount % SBL_CC2650_MAX_BYTES_PER_TRANSFER) ui32TotChunks++; + uint32_t ui32CurrChunk = 0; + + // + // Calculate BL configuration address (depends on flash size) + // + uint32_t ui32BlCfgAddr = getBootloaderEnableAddress(); + + // + // Calculate BL configuration buffer index + // + uint32_t ui32BlCfgDataIdx = ui32BlCfgAddr - ui32StartAddress; + + // + // Is BL configuration part of buffer? + // + if(ui32BlCfgDataIdx <= ui32ByteCount) + { + if(((pcData[ui32BlCfgDataIdx]) & 0xFF) != SBL_CC2650_BL_CONFIG_ENABLED_BM) + { + bBlToBeDisabled = true; + setState(SBL_SUCCESS, "Warning: Bootloader will be disabled.\n"); + } + } + + if(bBlToBeDisabled) + { + // + // Split into two transfers + // + pvTransfer.resize(2); + + // + // Main transfer (before lock bit) + // + pvTransfer[0].bExpectAck = true; + pvTransfer[0].startAddr = ui32StartAddress; + pvTransfer[0].byteCount = (ui32BlCfgAddr - ui32StartAddress) & (~0x03); + pvTransfer[0].startOffset = 0; + + // + // The transfer locking the backdoor + // + pvTransfer[1].bExpectAck = false; + pvTransfer[1].startAddr = ui32BlCfgAddr - (ui32BlCfgAddr % 4); + pvTransfer[1].byteCount = ui32ByteCount - pvTransfer[0].byteCount; + pvTransfer[1].startOffset = ui32BlCfgDataIdx - (ui32BlCfgDataIdx % 4); + + } + else + { + pvTransfer.resize(1); + pvTransfer[0].bExpectAck = true; + pvTransfer[0].byteCount = ui32ByteCount; + pvTransfer[0].startAddr = ui32StartAddress; + pvTransfer[0].startOffset = 0; + } + + // + // For each transfer + // + for(uint32_t i = 0; i < pvTransfer.size(); i++) + { + // + // Sanity check + // + if(pvTransfer[i].byteCount == 0) + { + continue; + } + + // + // Send download command + // + if((retCode = cmdDownload(pvTransfer[i].startAddr, + pvTransfer[i].byteCount)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Check status after download command + // + retCode = readStatus(&devStatus); + if(retCode != SBL_SUCCESS) + { + setState(retCode, "Error during download initialization. Failed to read device status after sending download command.\n"); + return retCode; + } + if(devStatus != SblDeviceCC2650::CMD_RET_SUCCESS) + { + setState(SBL_ERROR, "Error during download initialization. Device returned status %d (%s).\n", devStatus, getCmdStatusString(devStatus).c_str()); + return SBL_ERROR; + } + + // + // Send data in chunks + // + bytesLeft = pvTransfer[i].byteCount; + dataIdx = pvTransfer[i].startOffset; + while(bytesLeft) + { + // + // Set progress + // + //setProgress(addressToPage(ui32StartAddress + dataIdx)); + setProgress( ((100*(++ui32CurrChunk))/ui32TotChunks) ); + + // + // Limit transfer count + // +#if 1 + bytesInTransfer = min(SBL_CC2650_MAX_BYTES_PER_TRANSFER, bytesLeft); +#else + if(bytesLeft > SBL_CC2650_MAX_BYTES_PER_TRANSFER) + { + bytesInTransfer = SBL_CC2650_MAX_BYTES_PER_TRANSFER; + } else { + bytesInTransfer = bytesLeft; + } +#endif + + // + // Send Data command + // + if(retCode = cmdSendData(&pcData[dataIdx], bytesInTransfer) != SBL_SUCCESS) + { + setState(retCode, "Error during flash download. \n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d.\n", + (ui32StartAddress+dataIdx), + addressToPage(ui32StartAddress+dataIdx), + bytesInTransfer, + (transferNumber)); + return retCode; + } + + if(pvTransfer[i].bExpectAck) + { + // + // Check status after send data command + // + devStatus = 0; + retCode = readStatus(&devStatus); + if(retCode != SBL_SUCCESS) + { + setState(retCode, "Error during flash download. Failed to read device status.\n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d in chunk %d.\n", + (ui32StartAddress+dataIdx), + addressToPage(ui32StartAddress + dataIdx), + (bytesInTransfer), (transferNumber), + (i)); + return retCode; + } + if(devStatus != SblDeviceCC2650::CMD_RET_SUCCESS) + { + setState(SBL_SUCCESS, "Device returned status %s\n", getCmdStatusString(devStatus).c_str()); + if(bIsRetry) + { + // + // We have failed a second time. Aborting. + setState(SBL_ERROR, "Error retrying flash download.\n- Start address 0x%08X (page %d). \n- Tried to transfer %d bytes. \n- This was transfer %d in chunk %d.\n", + (ui32StartAddress+dataIdx), + addressToPage(ui32StartAddress + dataIdx), + (bytesInTransfer), (transferNumber), + (i)); + return SBL_ERROR; + } + + // + // Retry to send data one more time. + // + bIsRetry = true; + continue; + } + } + else + { + // + // We're locking device and will lose access + // + m_bCommInitialized = false; + + } + + // + // Update index and bytesLeft + // + bytesLeft -= bytesInTransfer; + dataIdx += bytesInTransfer; + transferNumber++; + bIsRetry = false; + } + } + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Erases all customer accessible flash sectors not protected by FCFG1 + * + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::eraseFlashBank() +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bResponse = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_BANK_ERASE)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Get response + // + if((retCode = getCmdResponse(bResponse)) != SBL_SUCCESS) + { + return retCode; + } + + return (bResponse) ? SBL_SUCCESS : SBL_ERROR; +} + + +//----------------------------------------------------------------------------- +/** \brief Writes the CC26xx defined CCFG fields to the flash CCFG area with + * the values received in the data bytes of this command. + * + * \param[in] ui32Field + * CCFG Field ID which identifies the CCFG parameter to be written. + * \param[in] ui32FieldValue + * Field value to be programmed. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- + +uint32_t SblDeviceCC2650::setCCFG(uint32_t ui32Field, uint32_t ui32FieldValue){ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + if(!isConnected()) + { + return SBL_PORT_ERROR; + } + + // + // Generate payload + // - 4B Field ID + // - 4B Field value + // + char pcPayload[8]; + ulToCharArray(ui32Field, &pcPayload[0]); + ulToCharArray(ui32FieldValue, &pcPayload[4]); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_SET_CCFG, pcPayload, 8)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + setState(SBL_ERROR, "Set CCFG command NAKed by device.\n"); + return SBL_ERROR; + } + + + return SBL_SUCCESS; +} + +//----------------------------------------------------------------------------- +/** \brief Send command. + * + * \param[in] ui32Cmd + * The command to send. + * \param[in] pcSendData + * Pointer to the data to send with the command. + * \param[in] ui32SendLen + * The number of bytes to send from \e pcSendData. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::sendCmd(uint32_t ui32Cmd, const char *pcSendData/* = NULL*/, + uint32_t ui32SendLen/* = 0*/) +{ + DEBUG_PRINT("\n"); + // + // Handle command ID for early versions + // + ui32Cmd = convertCmdForEarlySamples(ui32Cmd); + + + unsigned char pktLen = ui32SendLen + 3; // +3 => <1b Length>, <1B checksum>, <1B cmd> + std::vector pvPkt((pktLen)); + unsigned char pktSum = generateCheckSum(ui32Cmd, pcSendData, ui32SendLen); + + // + // Build packet + // + pvPkt.at(0) = pktLen; + pvPkt.at(1) = pktSum; + pvPkt.at(2) = (unsigned char)ui32Cmd; + if(ui32SendLen) + { + memcpy(&pvPkt[3], pcSendData, ui32SendLen); + } + + // + // Send packet + // + if(m_pCom->writeBytes(&pvPkt[0], pvPkt.size()) < 1) + { + setState(SBL_PORT_ERROR, "\nWriting to device failed (Command 0x%04x:'%s').\n", ui32Cmd,getCmdString(ui32Cmd).c_str()); + return SBL_PORT_ERROR; + } + // + // Empty and deallocate vector + // + pvPkt.clear(); + std::vector().swap(pvPkt); + + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief Initialize connection to the CC2650 device. + * + * \param[in] bSetXosc + * If true, try to enable device XOSC. + * \return + * Returns SBL_SUCCESS, ... + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::initCommunication(bool bSetXosc) +{ + DEBUG_PRINT("\n"); + bool bSuccess, bBaudSetOk; + int retCode = SBL_ERROR; + + // + // Send dummy command to see if device is already initialized at + // this baud rate. + // + if(sendCmd(0) != SBL_SUCCESS) + { + return SBL_ERROR; + } + + // + // Do we get a response (ACK/NAK)? + // + bSuccess = false; + if(getCmdResponse(bSuccess, SBL_DEFAULT_RETRY_COUNT, true) != SBL_SUCCESS) + { + // + // No response received. Try auto baud + // + if(retCode = sendAutoBaud(bBaudSetOk) != SBL_SUCCESS) + { + return retCode; + } + } + + + m_bCommInitialized = true; + return SBL_SUCCESS; +} + + +//----------------------------------------------------------------------------- +/** \brief This function returns a string with the device command name of + * \e ui32Cmd. + * + * \param[out] ui32Cmd + * The serial bootloader command. + * \return + * Returns std::string with name of device command. + */ +//----------------------------------------------------------------------------- +std::string +SblDeviceCC2650::getCmdString(uint32_t ui32Cmd) +{ + DEBUG_PRINT("\n"); + switch(ui32Cmd) + { + case SblDeviceCC2650::CMD_PING: return "CMD_PING"; break; + case SblDeviceCC2650::CMD_CRC32: return "CMD_CRC32"; break; + case SblDeviceCC2650::CMD_DOWNLOAD: return "CMD_DOWNLOAD"; break; + case SblDeviceCC2650::CMD_GET_CHIP_ID: return "CMD_GET_CHIP_ID"; break; + case SblDeviceCC2650::CMD_GET_STATUS: return "CMD_GET_STATUS"; break; + case SblDeviceCC2650::CMD_MEMORY_READ: return "CMD_MEMORY_READ"; break; + case SblDeviceCC2650::CMD_MEMORY_WRITE: return "CMD_MEMORY_WRITE"; break; + case SblDeviceCC2650::CMD_RESET: return "CMD_RESET"; break; + default: return "Unknown command"; break; + } +} + + +//----------------------------------------------------------------------------- +/** \brief This function returns a string with the device status name of + * \e ui32Status serial bootloader status value. + * + * \param[out] ui32Status + * The serial bootloader status value. + * \return + * Returns std::string with name of device status. + */ +//----------------------------------------------------------------------------- +std::string +SblDeviceCC2650::getCmdStatusString(uint32_t ui32Status) +{ + DEBUG_PRINT("\n"); + switch(ui32Status) + { + case SblDeviceCC2650::CMD_RET_FLASH_FAIL: return "FLASH_FAIL"; break; + case SblDeviceCC2650::CMD_RET_INVALID_ADR: return "INVALID_ADR"; break; + case SblDeviceCC2650::CMD_RET_INVALID_CMD: return "INVALID_CMD"; break; + case SblDeviceCC2650::CMD_RET_SUCCESS: return "SUCCESS"; break; + case SblDeviceCC2650::CMD_RET_UNKNOWN_CMD: return "UNKNOWN_CMD"; break; + default: return "Unknown status"; break; + } +} + + +//----------------------------------------------------------------------------- +/** \brief This function sends the CC2650 download command and handles the + * device response. + * + * \param[in] ui32Address + * The start address in CC2650 flash. + * \param[in] ui32Size + * The total number of bytes to program on the device. + * + * \return + * Returns SBL_SUCCESS if command and response was successful. + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::cmdDownload(uint32_t ui32Address, uint32_t ui32Size) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + + // + // Check input arguments + // + if(!addressInFlash(ui32Address, ui32Size)) + { + setState(SBL_ARGUMENT_ERROR, "Flash download: Address range (0x%08X + %d bytes) is not in device FLASH nor RAM.\n", ui32Address, ui32Size); + return SBL_ARGUMENT_ERROR; + } + if(ui32Size & 0x03) + { + setState(SBL_ARGUMENT_ERROR, "Flash download: Byte count must be a multiple of 4\n"); + return SBL_ARGUMENT_ERROR; + } + + // + // Generate payload + // - 4B Program address + // - 4B Program size + // + char pcPayload[8]; + ulToCharArray(ui32Address, &pcPayload[0]); + ulToCharArray(ui32Size, &pcPayload[4]); + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_DOWNLOAD, pcPayload, 8)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Return command response + // + return (bSuccess) ? SBL_SUCCESS : SBL_ERROR; +} + + +//----------------------------------------------------------------------------- +/** \brief This function sends the CC2650 SendData command and handles the + * device response. + * + * \param[in] pcData + * Pointer to the data to send. + * \param[in] ui32ByteCount + * The number of bytes to send. + * + * \return + * Returns SBL_SUCCESS if command and response was successful. + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::cmdSendData(const char *pcData, uint32_t ui32ByteCount) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if(ui32ByteCount > SBL_CC2650_MAX_BYTES_PER_TRANSFER) + { + setState(SBL_ERROR, "Error: Byte count (%d) exceeds maximum transfer size %d.\n", ui32ByteCount, SBL_CC2650_MAX_BYTES_PER_TRANSFER); + return SBL_ERROR; + } + + // + // Send command + // + if((retCode = sendCmd(SblDeviceCC2650::CMD_SEND_DATA, pcData, ui32ByteCount)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if((retCode = getCmdResponse(bSuccess, 3)) != SBL_SUCCESS) + { + return retCode; + } + if(!bSuccess) + { + return SBL_ERROR; + } + + return SBL_SUCCESS; +} + +//----------------------------------------------------------------------------- +/** \brief This function returns the page within which address \e ui32Address + * is located. + * + * \param[in] ui32Address + * The address. + * + * \return + * Returns the flash page within which an address is located. + */ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::addressToPage(uint32_t ui32Address) +{ + DEBUG_PRINT("\n"); + return ((ui32Address - SBL_CC2650_FLASH_START_ADDRESS) / getPageEraseSize() ); +} + + +//----------------------------------------------------------------------------- +/** \brief This function checks if the specified \e ui32StartAddress (and range) + * is located within the device RAM area. + * + * \param[in] ui32StartAddress + * The start address of the range + * \param[in] pui32Bytecount + * (Optional) The number of bytes in the range. + * \return + * Returns true if the address/range is within the device RAM. + */ +//----------------------------------------------------------------------------- +bool +SblDeviceCC2650::addressInRam(uint32_t ui32StartAddress, + uint32_t ui32ByteCount/* = 1*/) +{ + DEBUG_PRINT("\n"); + uint32_t ui32EndAddr = ui32StartAddress + ui32ByteCount; + + if(ui32StartAddress < SBL_CC2650_RAM_START_ADDRESS) + { + return false; + } + if(ui32EndAddr > (SBL_CC2650_RAM_START_ADDRESS + getRamSize())) + { + return false; + } + return true; +} + + +//----------------------------------------------------------------------------- +/** \brief This function checks if the specified \e ui32StartAddress (and range) + * is located within the device FLASH area. + * + * \param[in] ui32StartAddress + * The start address of the range + * \param[in] pui32Bytecount + * (Optional) The number of bytes in the range. + * + * \return + * Returns true if the address/range is within the device RAM. + */ +//----------------------------------------------------------------------------- +bool +SblDeviceCC2650::addressInFlash(uint32_t ui32StartAddress, + uint32_t ui32ByteCount/* = 1*/) +{ + DEBUG_PRINT("\n"); + uint32_t ui32EndAddr = ui32StartAddress + ui32ByteCount; + + if(ui32EndAddr > (SBL_CC2650_FLASH_START_ADDRESS + getFlashSize())) + { + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +/** \brief This function returns the FLASH address of the bootloader enable +* configuration. +* +* \return +* Returns true if the address/range is within the device RAM. +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2650::getBootloaderEnableAddress() +{ + DEBUG_PRINT("\n"); + return SBL_CC2650_FLASH_START_ADDRESS + getFlashSize() - getPageEraseSize() + SBL_CC2650_BL_CONFIG_PAGE_OFFSET; +} + +//----------------------------------------------------------------------------- +/** \brief This function checks if the specified \e ui32StartAddress (and range) + * overlaps the bootloader's working memory or stack area. + * + * The bootloader does not protect against writing to these ranges, but + * doing so is almost guaranteed to crash the bootloader and requires a + * reboot. SRAM ranges used by the bootloader: + * \li Work memory @ 0x20000000-0x2000016F + * \li Stack area @ 0x20000FC0-0x20000FFF + * + * \param[in] ui32StartAddress + * The start address of the range + * \param[in] pui32Bytecount + * (Optional) The number of bytes in the range. + * + * \return + * Returns true if the address/range is within the device RAM. + */ +//----------------------------------------------------------------------------- +bool +SblDeviceCC2650::addressInBLWorkMemory(uint32_t ui32StartAddress, + uint32_t ui32ByteCount/* = 1*/) +{ + DEBUG_PRINT("\n"); + uint32_t ui32EndAddr = ui32StartAddress + ui32ByteCount; + + if(ui32StartAddress <= SBL_CC2650_BL_WORK_MEMORY_END) + { + return true; + } + if((ui32StartAddress >= SBL_CC2650_BL_STACK_MEMORY_START) && + (ui32StartAddress <= SBL_CC2650_BL_STACK_MEMORY_END)) + { + return true; + } + if((ui32EndAddr >= SBL_CC2650_BL_STACK_MEMORY_START) && + (ui32EndAddr <= SBL_CC2650_BL_STACK_MEMORY_END)) + { + return true; + } + return false; +} + + +//----------------------------------------------------------------------------- +/** \brief This function converts the command ID if the connected device + * is an early version. Affected commands are + * \li CMD_MEMORY_READ + * \li CMD_MEMORY_WRITE + * \li CMD_SET_CCFG + * \li CMD_BANK_ERASE + * + * \param[in] ui32Cmd + * The command that must be converted. + * + * \return + * Returns the correct command ID for the connected device. + */ +//----------------------------------------------------------------------------- +uint32_t SblDeviceCC2650::convertCmdForEarlySamples(uint32_t ui32Cmd) +{ + DEBUG_PRINT("\n"); + if(m_deviceRev != 1) + { + // No conversion needed, return early. + return ui32Cmd; + } + switch(ui32Cmd) + { + case SblDeviceCC2650::CMD_MEMORY_READ: + return SblDeviceCC2650::REV1_CMD_MEMORY_READ; + case SblDeviceCC2650::CMD_MEMORY_WRITE: + return SblDeviceCC2650::REV1_CMD_MEMORY_WRITE; + case SblDeviceCC2650::CMD_SET_CCFG: + return SblDeviceCC2650::REV1_CMD_SET_CCFG; + case SblDeviceCC2650::CMD_BANK_ERASE: + return SblDeviceCC2650::REV1_CMD_BANK_ERASE; + default: + // No conversion needed, return original command. + return ui32Cmd; + } +} diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2650.h b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2650.h new file mode 100755 index 000000000..0a0f742d3 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2650.h @@ -0,0 +1,153 @@ +#ifndef __SBL_DEVICE_CC2650_H__ +#define __SBL_DEVICE_CC2650_H__ +/****************************************************************************** +* Filename: sbl_device_cc2650.h +* Revised: $Date: 2013-07-26 09:53:42 +0200 (fr, 26 jul 2013) $ +* Revision: $Revision: 26971 $ +* +* Description: Serial Bootloader for CC2650 header file. +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ +#include + + +#define SBL_CC2650_PAGE_ERASE_SIZE 4096 +#define SBL_CC2650_FLASH_START_ADDRESS 0x00000000 +#define SBL_CC2650_RAM_START_ADDRESS 0x20000000 +#define SBL_CC2650_ACCESS_WIDTH_32B 1 +#define SBL_CC2650_ACCESS_WIDTH_8B 0 +#define SBL_CC2650_PAGE_ERASE_TIME_MS 20 +#define SBL_CC2650_MAX_BYTES_PER_TRANSFER 252 +#define SBL_CC2650_MAX_MEMWRITE_BYTES 247 +#define SBL_CC2650_MAX_MEMWRITE_WORDS 61 +#define SBL_CC2650_MAX_MEMREAD_BYTES 253 +#define SBL_CC2650_MAX_MEMREAD_WORDS 63 +#define SBL_CC2650_FLASH_SIZE_CFG 0x4003002C +#define SBL_CC2650_RAM_SIZE_CFG 0x40082250 +#define SBL_CC2650_BL_CONFIG_PAGE_OFFSET 0xFDB +#define SBL_CC2650_BL_CONFIG_ENABLED_BM 0xC5 +#define SBL_CC2650_BL_WORK_MEMORY_START 0x20000000 +#define SBL_CC2650_BL_WORK_MEMORY_END 0x2000016F +#define SBL_CC2650_BL_STACK_MEMORY_START 0x20000FC0 +#define SBL_CC2650_BL_STACK_MEMORY_END 0x20000FFF + +class SblDeviceCC2650 : public SblDevice +{ +public: + SblDeviceCC2650(); // Constructor + ~SblDeviceCC2650(); // Destructor + + enum { + CMD_PING = 0x20, + CMD_DOWNLOAD = 0x21, + CMD_GET_STATUS = 0x23, + CMD_SEND_DATA = 0x24, + CMD_RESET = 0x25, + CMD_SECTOR_ERASE = 0x26, + CMD_CRC32 = 0x27, + CMD_GET_CHIP_ID = 0x28, + CMD_MEMORY_READ = 0x2A, + CMD_MEMORY_WRITE = 0x2B, + CMD_BANK_ERASE = 0x2C, + CMD_SET_CCFG = 0x2D, + }; + + /* Early samples had different command IDs */ + enum + { + REV1_CMD_BANK_ERASE = 0x2A, + REV1_CMD_SET_CCFG = 0x2B, + REV1_CMD_MEMORY_READ = 0x2C, + REV1_CMD_MEMORY_WRITE = 0x2D, + }; + + enum { + CMD_RET_SUCCESS = 0x40, + CMD_RET_UNKNOWN_CMD = 0x41, + CMD_RET_INVALID_CMD = 0x42, + CMD_RET_INVALID_ADR = 0x43, + CMD_RET_FLASH_FAIL = 0x44, + }; + +protected: + + // Virtual functions from SblDevice + uint32_t ping(); + + uint32_t readStatus(uint32_t *pui32Status); + uint32_t readDeviceId(uint32_t *pui32DeviceId); + virtual uint32_t readFlashSize(uint32_t *pui32FlashSize); + virtual uint32_t readRamSize(uint32_t *pui32RamSize); + + uint32_t reset(); + uint32_t eraseFlashRange(uint32_t ui32StartAddress, uint32_t ui32ByteCount); + uint32_t writeFlashRange(uint32_t ui32StartAddress, uint32_t ui32ByteCount, const char *pcData); + + + uint32_t readMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, uint32_t *pui32Data); + uint32_t readMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, char *pcData); + uint32_t writeMemory32(uint32_t ui32StartAddress, uint32_t ui32UnitCount, const uint32_t *pui32Data); + uint32_t writeMemory8(uint32_t ui32StartAddress, uint32_t ui32UnitCount, const char *pcData); + + uint32_t calculateCrc32(uint32_t ui32StartAddress, uint32_t ui32ByteCount, uint32_t *pui32Crc); + + uint32_t sendCmd(uint32_t ui32Cmd, const char *pcSendData = NULL, uint32_t ui32SendLen = 0); + std::string getCmdString(uint32_t ui32Cmd); + uint32_t addressToPage(uint32_t ui32Address); + bool addressInRam(uint32_t ui32StartAddress, uint32_t ui32ByteCount = 1); + bool addressInFlash(uint32_t ui32StartAddress, uint32_t ui32ByteCount = 1); + + uint32_t convertCmdForEarlySamples(uint32_t ui32Cmd); + + virtual uint32_t getBootloaderEnableAddress(); + + // CC2650 specific + uint32_t eraseFlashBank(); + uint32_t setCCFG(uint32_t ui32Field, uint32_t ui32FieldValue); + + // Device revision. Used internally by SBL to handle early samples with different command IDs. + uint32_t m_deviceRev; +private: + uint32_t initCommunication(bool bSetXosc); + uint32_t cmdDownload(uint32_t ui32Address, uint32_t ui32Size); + uint32_t cmdSendData(const char *pcData, uint32_t ui32ByteCount); + + std::string getCmdStatusString(uint32_t ui32Status); + + bool addressInBLWorkMemory(uint32_t ui32StartAddr, uint32_t ui32ByteCount = 1); + + +}; + + +#endif // __SBL_DEVICE_CC2650_H__ diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2652.cpp b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2652.cpp new file mode 100755 index 000000000..49fb0d564 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2652.cpp @@ -0,0 +1,330 @@ +/****************************************************************************** +* Filename: sbl_device_cc2652.cpp +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader device file for CC13x2/CC26x2 +* +* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include +#include "sbl_device.h" +#include "sbl_device_cc2652.h" + +#include "serialib.h" + + +//----------------------------------------------------------------------------- +/** \brief Constructor +*/ +//----------------------------------------------------------------------------- +SblDeviceCC2652::SblDeviceCC2652() : SblDeviceCC2650() +{ + DEBUG_PRINT("\n"); + m_pageEraseSize = SBL_CC2652_PAGE_ERASE_SIZE; +} + +//----------------------------------------------------------------------------- +/** \brief Destructor +*/ +//----------------------------------------------------------------------------- +SblDeviceCC2652::~SblDeviceCC2652() +{ + DEBUG_PRINT("\n"); +} + +//----------------------------------------------------------------------------- +/** \brief This function reads device FLASH size in bytes. +* +* \param[out] pui32FlashSize +* Pointer to where FLASH size is stored. +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2652::readFlashSize(uint32_t *pui32FlashSize) +{ + DEBUG_PRINT("\n"); + uint32_t retCode = SBL_SUCCESS; + + // + // Read CC2652 DIECFG0 (contains FLASH size information) + // + uint32_t addr = SBL_CC2652_FLASH_SIZE_CFG; + uint32_t value; + if ((retCode = readMemory32(addr, 1, &value)) != SBL_SUCCESS) + { + setState((tSblStatus)retCode, "Failed to read device FLASH size: %s", getLastError().c_str()); + return retCode; + } + + // + // Calculate flash size (The number of flash sectors are at bits [7:0]) + // + value &= 0xFF; + *pui32FlashSize = value*SBL_CC2652_PAGE_ERASE_SIZE; + + m_flashSize = *pui32FlashSize; + + return SBL_SUCCESS; +} + +//----------------------------------------------------------------------------- +/** \brief This function reads device RAM size in bytes. +* +* \param[out] pui32RamSize +* Pointer to where RAM size is stored. +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2652::readRamSize(uint32_t *pui32RamSize) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + + uint32_t addr = SBL_CC2652_RAM_SIZE_CFG; + uint32_t value; + + if ((retCode = readMemory32(addr, 1, &value)) != SBL_SUCCESS) + { + setState(retCode, "Failed to read device RAM size: %s", getLastError().c_str()); + return retCode; + } + + uint32_t ramSizeInfo = (value & CHIP_SRAM_SIZE_INFO_M) >> CHIP_SRAM_SIZE_INFO_S; + + m_ramSize = calculateRamSize(ramSizeInfo); + + if (*pui32RamSize != NULL) + { + *pui32RamSize = m_ramSize; + } + + return retCode; +} + +//----------------------------------------------------------------------------- +/** \brief Calculate RAM size. +* +* \param[in] ramSizeInfo +* Register value for RAM size configuration (TOP:PRCM:RAMHWOPT). +* The argument is optional and the default value is 3 (RAM size 80 KB) +* \returns uint32_t +* Ram size +*/ +//----------------------------------------------------------------------------- +uint32_t SblDeviceCC2652::calculateRamSize(uint32_t ramSizeInfo) +{ + DEBUG_PRINT("\n"); + uint32_t ramSize; + + switch (ramSizeInfo) + { + case 0: + ramSize = (32 * 1024); + break; + case 1: + ramSize = (48 * 1024); + break; + case 2: + ramSize = (64 * 1024); + break; + case 3: + default: + ramSize = (80 * 1024); + break; + } + + return ramSize; + +} + +//----------------------------------------------------------------------------- +/** \brief This function returns the FLASH address of the bootloader enable +* configuration. +* +* \return +* Returns true if the address/range is within the device RAM. +*/ +//----------------------------------------------------------------------------- +uint32_t SblDeviceCC2652::getBootloaderEnableAddress() +{ + DEBUG_PRINT("\n"); + return SBL_CC2652_FLASH_START_ADDRESS + getFlashSize() - getPageEraseSize() + SBL_CC2652_BL_CONFIG_PAGE_OFFSET; +} + +//----------------------------------------------------------------------------- +/** \brief This function returns a string with the device command name of +* \e ui32Cmd. +* +* \param[out] ui32Cmd +* The serial bootloader command. +* \return +* Returns std::string with name of device command. +*/ +//----------------------------------------------------------------------------- +std::string +SblDeviceCC2652::getCmdString(uint32_t ui32Cmd) +{ + DEBUG_PRINT("\n"); + std::string cmd = SblDeviceCC2650::getCmdString(ui32Cmd); + if (cmd.find("Unknown") != std::string::npos) + { + switch (ui32Cmd) + { + case SblDeviceCC2652::CMD_DOWNLOAD_CRC: cmd = "CMD_DOWNLOAD_CRC"; break; + default: cmd = "Unknown command"; break; + } + } + + return cmd; +} + + +//----------------------------------------------------------------------------- +/** \brief This function sends the CC2652 download CRC command and handles the +* device response. +* +* \param[in] ui32Address +* The start address in CC2652 flash. +* \param[in] ui32Size +* Number of bytes to be sent. +* \param[in] ui32Crc +* Total number of bytes to be programmed. +* +* \return +* Returns SBL_SUCCESS if command and response was successful. +*/ +//----------------------------------------------------------------------------- +uint32_t SblDeviceCC2652::cmdDownloadCrc(uint32_t ui32Address, uint32_t ui32Size, uint32_t ui32Crc) +{ + DEBUG_PRINT("\n"); + int retCode = SBL_SUCCESS; + bool bSuccess = false; + + // + // Check input arguments + // + if (!addressInFlash(ui32Address, ui32Size) && + !addressInRam(ui32Address, ui32Size)) + { + setState(SBL_ARGUMENT_ERROR, "Specified address range (0x%08X + %d bytes) is not in device FLASH nor RAM.\n", ui32Address, ui32Size); + return SBL_ARGUMENT_ERROR; + } + + // + // Generate payload + // - 4B Program address + // - 4B Program data + // - 4B CRC + // + char pcPayload[12]; + ulToCharArray(ui32Address, &pcPayload[0]); + ulToCharArray(ui32Size, &pcPayload[4]); + ulToCharArray(ui32Crc, &pcPayload[8]); + + // + // Send command + // + if ((retCode = sendCmd(SblDeviceCC2652::CMD_DOWNLOAD_CRC, pcPayload, 12) != SBL_SUCCESS)) + { + return retCode; + } + + // + // Receive command response (ACK/NAK) + // + if ((retCode = getCmdResponse(bSuccess)) != SBL_SUCCESS) + { + return retCode; + } + + // + // Return command response + // + return (bSuccess) ? SBL_SUCCESS : SBL_ERROR; +} + +//----------------------------------------------------------------------------- +/** \brief Send command. +* +* \param[in] ui32Cmd +* The command to send. +* \param[in] pcSendData +* Pointer to the data to send with the command. +* \param[in] ui32SendLen +* The number of bytes to send from \e pcSendData. +* \return +* Returns SBL_SUCCESS, ... +*/ +//----------------------------------------------------------------------------- +uint32_t +SblDeviceCC2652::sendCmd(uint32_t ui32Cmd, const char *pcSendData/* = NULL*/, + uint32_t ui32SendLen/* = 0*/) +{ + DEBUG_PRINT("\n"); + unsigned char pktLen = ui32SendLen + 3; // +3 => <1B Length>, <1B checksum>, <1B cmd> + std::vector pvPkt((pktLen)); + unsigned char pktSum = generateCheckSum(ui32Cmd, pcSendData, ui32SendLen); + + // + // Build packet + // + pvPkt.at(0) = pktLen; + pvPkt.at(1) = pktSum; + pvPkt.at(2) = (unsigned char)ui32Cmd; + if (ui32SendLen) + { + memcpy(&pvPkt[3], pcSendData, ui32SendLen); + } + + // + // Send packet + // + if (m_pCom->writeBytes(&pvPkt[0], pvPkt.size()) < 1) + { + setState(SBL_PORT_ERROR, "\nWriting to device failed (Command 0x%04x:'%s').\n", ui32Cmd,getCmdString(ui32Cmd).c_str()); + return SBL_PORT_ERROR; + } + // + // Empty and deallocate vector + // + pvPkt.clear(); + std::vector().swap(pvPkt); + + return SBL_SUCCESS; +} + diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2652.h b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2652.h new file mode 100755 index 000000000..914b381cd --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_device_cc2652.h @@ -0,0 +1,77 @@ +#ifndef __SBL_DEVICE_CC2652_H__ +#define __SBL_DEVICE_CC2652_H__ +/****************************************************************************** +* Filename: sbl_device_cc2652.h +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader for CC13x2/CC26x2 header file. +* +* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ +#include "sbl_device_cc2650.h" + +#define SBL_CC2652_PAGE_ERASE_SIZE 8192 +#define SBL_CC2652_FLASH_SIZE_CFG 0x4003002C +#define SBL_CC2652_RAM_SIZE_CFG 0x40082250 +#define SBL_CC2652_RAM_SIZE_CFG 0x40082250 +#define SBL_CC2652_FLASH_START_ADDRESS SBL_CC2650_FLASH_START_ADDRESS +#define SBL_CC2652_BL_CONFIG_PAGE_OFFSET 0x1FDB + +#define CHIP_SRAM_SIZE_INFO 0x40082250 +#define CHIP_SRAM_SIZE_INFO_M 0x00000003 +#define CHIP_SRAM_SIZE_INFO_S 0 + +class SblDeviceCC2652 : public SblDeviceCC2650 +{ +public: + SblDeviceCC2652(); // Constructor + ~SblDeviceCC2652(); // Destructor + + enum { + CMD_DOWNLOAD_CRC = 0x2F, + }; + +protected: + uint32_t readFlashSize(uint32_t *pui32FlashSize); + uint32_t readRamSize(uint32_t *pui32RamSize); + uint32_t calculateRamSize(uint32_t ramSizeInfo); + uint32_t getBootloaderEnableAddress(); + +private: + std::string getCmdString(uint32_t ui32Cmd); + uint32_t sendCmd(uint32_t ui32Cmd, const char *pcSendData = NULL, uint32_t ui32SendLen = 0); + uint32_t cmdDownloadCrc(uint32_t ui32Address, uint32_t ui32Size, uint32_t uiCrc); + +}; + +#endif // __SBL_DEVICE_CC2652_H__ diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbl_eb_info.h b/feeds/bluetooth-cc2652/cc2652/src/sbl_eb_info.h new file mode 100755 index 000000000..e0c670764 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbl_eb_info.h @@ -0,0 +1,66 @@ +#ifndef __SBL_EB_INFO_H__ +#define __SBL_EB_INFO_H__ +/****************************************************************************** +* Filename: sbl_eb_info.h +* Revised: $Date: 2013-07-09 15:06:47 +0200 (Tue, 09 Jul 2013) $ +* Revision: $Revision: 26800 $ +* +* Description: Serial Bootloader EB info class header file. +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ +#include + +class SblEbInfo +{ +public: + enum + { + DEVICE_NAME_SIZE = 15, + EB_PORT_SIZE = 16, + DESCRIPTION_SIZE = 256 + }; + + char ebPort[EB_PORT_SIZE]; // E.g. COM42 + char ebDescription[DESCRIPTION_SIZE]; + char devName[DEVICE_NAME_SIZE]; // E.g. CC2538 for CC2650 + + SblEbInfo& operator = (const SblEbInfo& other) { + strncpy(ebPort, other.ebPort, EB_PORT_SIZE); + strncpy(ebDescription, other.ebDescription, DESCRIPTION_SIZE); + strncpy(devName, other.devName, DEVICE_NAME_SIZE); + return *this; + } + +}; + +#endif // __SBL_EB_INFO_H__ \ No newline at end of file diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbllib.cpp b/feeds/bluetooth-cc2652/cc2652/src/sbllib.cpp new file mode 100755 index 000000000..d583e772d --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbllib.cpp @@ -0,0 +1,39 @@ +/****************************************************************************** +* Filename: sbllib.cpp +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader Library main file. +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + diff --git a/feeds/bluetooth-cc2652/cc2652/src/sbllib.h b/feeds/bluetooth-cc2652/cc2652/src/sbllib.h new file mode 100755 index 000000000..5a92eb9c0 --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/sbllib.h @@ -0,0 +1,69 @@ +#ifndef __SBLLIB_H__ +#define __SBLLIB_H__ +/****************************************************************************** +* Filename: sbllib.h +* Revised: $Date$ +* Revision: $Revision$ +* +* Description: Serial Bootloader Library header file. +* +* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ +#include +#include + +#include "debug.h" +#define SBL_MAX_DEVICES 20 +#define SBL_DEFAULT_RETRY_COUNT 1 +#define SBL_DEFAULT_READ_TIMEOUT 100 // in ms +#define SBL_DEFAULT_WRITE_TIMEOUT 200 // in ms + +typedef enum { + SBL_SUCCESS = 0, + SBL_ERROR, + SBL_ARGUMENT_ERROR, + SBL_TIMEOUT_ERROR, + SBL_PORT_ERROR, + SBL_ENUM_ERROR, + SBL_UNSUPPORTED_FUNCTION, +} tSblStatus; + +#include "serialib.h" +#include "sbl_device.h" +#include "sbl_device_cc2538.h" +#include "sbl_device_cc2650.h" +#include "sbl_device_cc2652.h" +#include "sbl_eb_info.h" + + + +#endif // __SBLLIB_H__ diff --git a/feeds/bluetooth-cc2652/cc2652/src/serialib.cpp b/feeds/bluetooth-cc2652/cc2652/src/serialib.cpp new file mode 100755 index 000000000..1a01badce --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/serialib.cpp @@ -0,0 +1,1019 @@ +/*! + \file serialib.cpp + \brief Source file of the class serialib. This class is used for communication over a serial device. + \author Philippe Lucidarme (University of Angers) + \version 2.0 + \date december the 27th of 2019 + +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 X CONSORTIUM 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. + + +This is a licence-free software, it can be used by anyone who try to build a better world. + */ +#include "debug.h" +#include "serialib.h" + +//_____________________________________ +// ::: Constructors and destructors ::: + + +/*! + \brief Constructor of the class serialib. +*/ +serialib::serialib() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined( _WIN64) + // Set default value for RTS and DTR (Windows only) + currentStateRTS=true; + currentStateDTR=true; +#endif +} + + +/*! + \brief Destructor of the class serialib. It close the connection +*/ +// Class desctructor +serialib::~serialib() +{ + DEBUG_PRINT("\n"); + closeDevice(); +} + + + +//_________________________________________ +// ::: Configuration and initialization ::: + + + +/*! + \brief Open the serial port + \param Device : Port name (COM1, COM2, ... for Windows ) or (/dev/ttyS0, /dev/ttyACM0, /dev/ttyUSB0 ... for linux) + \param Bauds : Baud rate of the serial port. + + \n Supported baud rate for Windows : + - 110 + - 300 + - 600 + - 1200 + - 2400 + - 4800 + - 9600 + - 14400 + - 19200 + - 38400 + - 56000 + - 57600 + - 115200 + - 128000 + - 256000 + + \n Supported baud rate for Linux :\n + - 110 + - 300 + - 600 + - 1200 + - 2400 + - 4800 + - 9600 + - 19200 + - 38400 + - 57600 + - 115200 + + \return 1 success + \return -1 device not found + \return -2 error while opening the device + \return -3 error while getting port parameters + \return -4 Speed (Bauds) not recognized + \return -5 error while writing port parameters + \return -6 error while writing timeout parameters + */ +char serialib::openDevice(const char *Device,const unsigned int Bauds) +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined( _WIN64) + // Open serial port + hSerial = CreateFileA(Device,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + if(hSerial==INVALID_HANDLE_VALUE) { + if(GetLastError()==ERROR_FILE_NOT_FOUND) + return -1; // Device not found + + // Error while opening the device + return -2; + } + + // Set parameters + + // Structure for the port parameters + DCB dcbSerialParams; + dcbSerialParams.DCBlength=sizeof(dcbSerialParams); + + // Get the port parameters + if (!GetCommState(hSerial, &dcbSerialParams)) return -3; + + // Set the speed (Bauds) + switch (Bauds) + { + case 110 : dcbSerialParams.BaudRate=CBR_110; break; + case 300 : dcbSerialParams.BaudRate=CBR_300; break; + case 600 : dcbSerialParams.BaudRate=CBR_600; break; + case 1200 : dcbSerialParams.BaudRate=CBR_1200; break; + case 2400 : dcbSerialParams.BaudRate=CBR_2400; break; + case 4800 : dcbSerialParams.BaudRate=CBR_4800; break; + case 9600 : dcbSerialParams.BaudRate=CBR_9600; break; + case 14400 : dcbSerialParams.BaudRate=CBR_14400; break; + case 19200 : dcbSerialParams.BaudRate=CBR_19200; break; + case 38400 : dcbSerialParams.BaudRate=CBR_38400; break; + case 56000 : dcbSerialParams.BaudRate=CBR_56000; break; + case 57600 : dcbSerialParams.BaudRate=CBR_57600; break; + case 115200 : dcbSerialParams.BaudRate=CBR_115200; break; + case 128000 : dcbSerialParams.BaudRate=CBR_128000; break; + case 256000 : dcbSerialParams.BaudRate=CBR_256000; break; + default : return -4; + } + // 8 bit data + dcbSerialParams.ByteSize=8; + // One stop bit + dcbSerialParams.StopBits=ONESTOPBIT; + // No parity + dcbSerialParams.Parity=NOPARITY; + + // Write the parameters + if(!SetCommState(hSerial, &dcbSerialParams)) return -5; + + // Set TimeOut + + // Set the Timeout parameters + timeouts.ReadIntervalTimeout=0; + // No TimeOut + timeouts.ReadTotalTimeoutConstant=MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier=0; + timeouts.WriteTotalTimeoutConstant=MAXDWORD; + timeouts.WriteTotalTimeoutMultiplier=0; + + // Write the parameters + if(!SetCommTimeouts(hSerial, &timeouts)) return -6; + + // Opening successfull + return 1; +#endif +#ifdef __linux__ + // Structure with the device's options + struct termios options; + + + // Open device + fd = open(Device, O_RDWR | O_NOCTTY | O_NDELAY); + // If the device is not open, return -1 + if (fd == -1) return -2; + // Open the device in nonblocking mode + fcntl(fd, F_SETFL, FNDELAY); + + + // Get the current options of the port + tcgetattr(fd, &options); + // Clear all the options + bzero(&options, sizeof(options)); + + // Prepare speed (Bauds) + speed_t Speed; + switch (Bauds) + { + case 110 : Speed=B110; break; + case 300 : Speed=B300; break; + case 600 : Speed=B600; break; + case 1200 : Speed=B1200; break; + case 2400 : Speed=B2400; break; + case 4800 : Speed=B4800; break; + case 9600 : Speed=B9600; break; + case 19200 : Speed=B19200; break; + case 38400 : Speed=B38400; break; + case 57600 : Speed=B57600; break; + case 115200 : Speed=B115200; break; + case 230400 : Speed=B230400; break; + default : return -4; + } + // Set the baud rate + cfsetispeed(&options, Speed); + cfsetospeed(&options, Speed); + // Configure the device : 8 bits, no parity, no control + options.c_cflag |= ( CLOCAL | CREAD | CS8); + options.c_iflag |= ( IGNPAR | IGNBRK ); + // Timer unused + options.c_cc[VTIME]=0; + // At least on character before satisfy reading + options.c_cc[VMIN]=0; + // Activate the settings + tcsetattr(fd, TCSANOW, &options); + // Success + return (1); +#endif + +} + + +/*! + \brief Close the connection with the current device +*/ +void serialib::closeDevice() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined( _WIN64) + CloseHandle(hSerial); +#endif +#ifdef __linux__ + close (fd); +#endif +} + + + + +//___________________________________________ +// ::: Read/Write operation on characters ::: + + + +/*! + \brief Write a char on the current serial port + \param Byte : char to send on the port (must be terminated by '\0') + \return 1 success + \return -1 error while writting data + */ +char serialib::writeChar(const char Byte) +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined( _WIN64) + // Number of bytes written + DWORD dwBytesWritten; + // Write the char to the serial device + // Return -1 if an error occured + if(!WriteFile(hSerial,&Byte,1,&dwBytesWritten,NULL)) return -1; + // Write operation successfull + return 1; +#endif +#ifdef __linux__ + // Write the char + if (write(fd,&Byte,1)!=1) return -1; + + // Write operation successfull + return 1; +#endif +} + + + +//________________________________________ +// ::: Read/Write operation on strings ::: + + +/*! + \brief Write a string on the current serial port + \param receivedString : string to send on the port (must be terminated by '\0') + \return 1 success + \return -1 error while writting data + */ +char serialib::writeString(const char *receivedString) +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined( _WIN64) + // Number of bytes written + DWORD dwBytesWritten; + // Write the string + if(!WriteFile(hSerial,receivedString,strlen(receivedString),&dwBytesWritten,NULL)) + // Error while writing, return -1 + return -1; + // Write operation successfull + return 1; +#endif +#ifdef __linux__ + // Lenght of the string + int Lenght=strlen(receivedString); + // Write the string + if (write(fd,receivedString,Lenght)!=Lenght) return -1; + // Write operation successfull + return 1; +#endif +} + +// _____________________________________ +// ::: Read/Write operation on bytes ::: + + + +/*! + \brief Write an array of data on the current serial port + \param Buffer : array of bytes to send on the port + \param NbBytes : number of byte to send + \return 1 success + \return -1 error while writting data + */ +int serialib::writeBytes(const void *Buffer, const unsigned int NbBytes) +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined( _WIN64) + // Number of bytes written + DWORD dwBytesWritten; + // Write data + if(!WriteFile(hSerial, Buffer, NbBytes, &dwBytesWritten, NULL)) + // Error while writing, return -1 + return -1; + // Write operation successfull + return 1; +#endif +#ifdef __linux__ + // Write data + DEBUG_PRINT("Len=%d, Data=%02x %02x %02x %02x ...\n",NbBytes,((unsigned char *)Buffer)[0],((unsigned char *)Buffer)[1],((unsigned char *)Buffer)[2],((unsigned char *)Buffer)[3]); +#if 0 + { + int i; + for(i=0;i0 success, return the number of bytes read + \return -1 error while setting the Timeout + \return -2 error while reading the byte + \return -3 MaxNbBytes is reached + */ +int serialib::readStringNoTimeOut(char *receivedString,char finalChar,unsigned int maxNbBytes) +{ + DEBUG_PRINT("\n"); + // Number of characters read + unsigned int NbBytes=0; + // Returned value from Read + char charRead; + + // While the buffer is not full + while (NbBytes0 success, return the number of bytes read + \return 0 timeout is reached + \return -1 error while setting the Timeout + \return -2 error while reading the byte + \return -3 MaxNbBytes is reached + */ +int serialib::readString(char *receivedString,char finalChar,unsigned int maxNbBytes,unsigned int timeOut_ms) +{ + DEBUG_PRINT("\n"); + // Check if timeout is requested + if (timeOut_ms==0) return readStringNoTimeOut(receivedString,finalChar,maxNbBytes); + + // Number of bytes read + unsigned int nbBytes=0; + // Character read on serial device + char charRead; + // Timer used for timeout + timeOut timer; + long int timeOutParam; + + // Initialize the timer (for timeout) + timer.initTimer(); + + // While the buffer is not full + while (nbBytes0) + { + // Wait for a byte on the serial link with the remaining time as timeout + charRead=readChar(&receivedString[nbBytes],timeOutParam); + + // If a byte has been received + if (charRead==1) + { + // Check if the character received is the final one + if (receivedString[nbBytes]==finalChar) + { + // Final character: add the end character 0 + receivedString [++nbBytes]=0; + // Return the number of bytes read + return nbBytes; + } + // This is not the final character, just increase the number of bytes read + nbBytes++; + } + // Check if an error occured during reading char + // If an error occurend, return the error number + if (charRead<0) return charRead; + } + // Check if timeout is reached + if (timer.elapsedTime_ms()>timeOut_ms) + { + // Add the end caracter + receivedString[nbBytes]=0; + // Return 0 (timeout reached) + return 0; + } + } + + // Buffer is full : return -3 + return -3; +} + + +/*! + \brief Read an array of bytes from the serial device (with timeout) + \param buffer : array of bytes read from the serial device + \param maxNbBytes : maximum allowed number of bytes read + \param timeOut_ms : delay of timeout before giving up the reading + \param sleepDuration_us : delay of CPU relaxing in microseconds (Linux only) + In the reading loop, a sleep can be performed after each reading + This allows CPU to perform other tasks + \return >=0 return the number of bytes read before timeout or + requested data is completed + \return -1 error while setting the Timeout + \return -2 error while reading the byte + */ +int serialib::readBytes (void *buffer,unsigned int maxNbBytes,unsigned int timeOut_ms, unsigned int sleepDuration_us) +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + // Avoid warning while compiling + UNUSED(sleepDuration_us); + + // Number of bytes read + DWORD dwBytesRead = 0; + + // Set the TimeOut + timeouts.ReadTotalTimeoutConstant=(DWORD)timeOut_ms; + + // Write the parameters and return -1 if an error occrured + if(!SetCommTimeouts(hSerial, &timeouts)) return -1; + + + // Read the bytes from the serial device, return -2 if an error occured + if(!ReadFile(hSerial,buffer,(DWORD)maxNbBytes,&dwBytesRead, NULL)) return -2; + + // Return the byte read + return dwBytesRead; +#endif +#ifdef __linux__ + // Timer used for timeout + timeOut timer; + // Initialise the timer + timer.initTimer(); + unsigned int NbByteRead=0; + // While Timeout is not reached + while (timer.elapsedTime_ms()0) + { + // Increase the number of read bytes + NbByteRead+=Ret; + // Success : bytes has been read + if (NbByteRead>=maxNbBytes){ + DEBUG_PRINT("Len=%d, Data=%02x %02x %02x %02x ...\n",NbByteRead,((unsigned char *)buffer)[0],((unsigned char *)buffer)[1],((unsigned char *)buffer)[2],((unsigned char *)buffer)[3]); +// if(NbByteRead < 6) printf("@@serialib::readBytes Len=%d, Data=%02x %02x %02x %02x %02x %02x ...\n",NbByteRead,((unsigned char *)buffer)[0],((unsigned char *)buffer)[1],((unsigned char *)buffer)[2],((unsigned char *)buffer)[3],((unsigned char *)buffer)[4],((unsigned char *)buffer)[5]); +#if 0 + { + int i; + for(i=0;i=maxNbBytes){ + DEBUG_PRINT("Len=%d, Data=%02x %02x %02x %02x ...\n",NbByteRead,((unsigned char *)buffer)[0],((unsigned char *)buffer)[1],((unsigned char *)buffer)[2],((unsigned char *)buffer)[3]); +// if(NbByteRead < 6) printf("@@serialib::readBytes Len=%d, Data=%02x %02x %02x %02x %02x %02x ...\n",NbByteRead,((unsigned char *)buffer)[0],((unsigned char *)buffer)[1],((unsigned char *)buffer)[2],((unsigned char *)buffer)[3],((unsigned char *)buffer)[4],((unsigned char *)buffer)[5]); +#if 0 + { + int i; + for(i=0;isetDTR(); + else + // Unset DTR + return this->clearDTR(); +} + + +/*! + \brief Set the bit DTR (pin 4) + DTR stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::setDTR() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + // Set DTR + currentStateDTR=true; + return EscapeCommFunction(hSerial,SETDTR); +#endif +#ifdef __linux__ + // Set DTR + int status_DTR=0; + ioctl(fd, TIOCMGET, &status_DTR); + status_DTR |= TIOCM_DTR; + ioctl(fd, TIOCMSET, &status_DTR); + return true; +#endif +} + +/*! + \brief Clear the bit DTR (pin 4) + DTR stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::clearDTR() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + // Clear DTR + currentStateDTR=true; + return EscapeCommFunction(hSerial,CLRDTR); +#endif +#ifdef __linux__ + // Clear DTR + int status_DTR=0; + ioctl(fd, TIOCMGET, &status_DTR); + status_DTR &= ~TIOCM_DTR; + ioctl(fd, TIOCMSET, &status_DTR); + return true; +#endif +} + + + +/*! + \brief Set or unset the bit RTS (pin 7) + RTS stands for Data Termina Ready + Convenience method :This method calls setDTR and clearDTR + \param status = true set DTR + status = false unset DTR + \return false if the function fails + \return true if the function succeeds +*/ +bool serialib::RTS(bool status) +{ + DEBUG_PRINT("\n"); + if (status) + // Set RTS + return this->setRTS(); + else + // Unset RTS + return this->clearRTS(); +} + + +/*! + \brief Set the bit RTS (pin 7) + RTS stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::setRTS() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + // Set RTS + currentStateRTS=false; + return EscapeCommFunction(hSerial,SETRTS); +#endif +#ifdef __linux__ + // Set RTS + int status_RTS=0; + ioctl(fd, TIOCMGET, &status_RTS); + status_RTS |= TIOCM_RTS; + ioctl(fd, TIOCMSET, &status_RTS); + return true; +#endif +} + + + +/*! + \brief Clear the bit RTS (pin 7) + RTS stands for Data Terminal Ready + \return If the function fails, the return value is false + If the function succeeds, the return value is true. +*/ +bool serialib::clearRTS() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + // Clear RTS + currentStateRTS=false; + return EscapeCommFunction(hSerial,CLRRTS); +#endif +#ifdef __linux__ + // Clear RTS + int status_RTS=0; + ioctl(fd, TIOCMGET, &status_RTS); + status_RTS &= ~TIOCM_RTS; + ioctl(fd, TIOCMSET, &status_RTS); + return true; +#endif +} + + + + +/*! + \brief Get the CTS's status (pin 8) + CTS stands for Clear To Send + \return Return true if CTS is set otherwise false + */ +bool serialib::isCTS() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_CTS_ON; +#endif +#ifdef __linux__ + int status=0; + //Get the current status of the CTS bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_CTS; +#endif +} + + + +/*! + \brief Get the DSR's status (pin 6) + DSR stands for Data Set Ready + \return Return true if DTR is set otherwise false + */ +bool serialib::isDSR() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_DSR_ON; +#endif +#ifdef __linux__ + int status=0; + //Get the current status of the DSR bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_DSR; +#endif +} + + + + + + +/*! + \brief Get the DCD's status (pin 1) + CDC stands for Data Carrier Detect + \return true if DCD is set + \return false otherwise + */ +bool serialib::isDCD() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_RLSD_ON; +#endif +#ifdef __linux__ + int status=0; + //Get the current status of the DCD bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_CAR; +#endif +} + + +/*! + \brief Get the RING's status (pin 9) + Ring Indicator + \return Return true if RING is set otherwise false + */ +bool serialib::isRI() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + DWORD modemStat; + GetCommModemStatus(hSerial, &modemStat); + return modemStat & MS_RING_ON; +#endif +#ifdef __linux__ + int status=0; + //Get the current status of the RING bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_RNG; +#endif +} + + +/*! + \brief Get the DTR's status (pin 4) + DTR stands for Data Terminal Ready + May behave abnormally on Windows + \return Return true if CTS is set otherwise false + */ +bool serialib::isDTR() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined( _WIN64) + return currentStateDTR; +#endif +#ifdef __linux__ + int status=0; + //Get the current status of the DTR bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_DTR ; +#endif +} + + + +/*! + \brief Get the RTS's status (pin 7) + RTS stands for Request To Send + May behave abnormally on Windows + \return Return true if RTS is set otherwise false + */ +bool serialib::isRTS() +{ + DEBUG_PRINT("\n"); +#if defined (_WIN32) || defined(_WIN64) + return currentStateRTS; +#endif +#ifdef __linux__ + int status=0; + //Get the current status of the CTS bit + ioctl(fd, TIOCMGET, &status); + return status & TIOCM_RTS; +#endif +} + + + + + + +// ****************************************** +// Class timeOut +// ****************************************** + + +/*! + \brief Constructor of the class timeOut. +*/ +// Constructor +timeOut::timeOut() +{ + DEBUG_PRINT("\n"); +} + + +/*! + \brief Initialise the timer. It writes the current time of the day in the structure PreviousTime. +*/ +//Initialize the timer +void timeOut::initTimer() +{ + DEBUG_PRINT("\n"); + gettimeofday(&previousTime, NULL); +} + +/*! + \brief Returns the time elapsed since initialization. It write the current time of the day in the structure CurrentTime. + Then it returns the difference between CurrentTime and PreviousTime. + \return The number of microseconds elapsed since the functions InitTimer was called. + */ +//Return the elapsed time since initialization +unsigned long int timeOut::elapsedTime_ms() +{ +// DEBUG_PRINT("\n"); + // Current time + struct timeval CurrentTime; + // Number of seconds and microseconds since last call + int sec,usec; + + // Get current time + gettimeofday(&CurrentTime, NULL); + + // Compute the number of seconds and microseconds elapsed since last call + sec=CurrentTime.tv_sec-previousTime.tv_sec; + usec=CurrentTime.tv_usec-previousTime.tv_usec; + + // If the previous usec is higher than the current one + if (usec<0) + { + // Recompute the microseonds and substract one second + usec=1000000-previousTime.tv_usec+CurrentTime.tv_usec; + sec--; + } + + // Return the elapsed time in milliseconds + return sec*1000+usec/1000; +} + + + + diff --git a/feeds/bluetooth-cc2652/cc2652/src/serialib.h b/feeds/bluetooth-cc2652/cc2652/src/serialib.h new file mode 100755 index 000000000..4bfb445bf --- /dev/null +++ b/feeds/bluetooth-cc2652/cc2652/src/serialib.h @@ -0,0 +1,220 @@ +/*! +\file serialib.h +\brief Header file of the class serialib. This class is used for communication over a serial device. +\author Philippe Lucidarme (University of Angers) +\version 2.0 +\date december the 27th of 2019 +This Serial library is used to communicate through serial port. + +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 X CONSORTIUM 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. + +This is a licence-free software, it can be used by anyone who try to build a better world. +*/ + + +#ifndef SERIALIB_H +#define SERIALIB_H + + + +// Used for TimeOut operations +#include +// Include for windows +#if defined (_WIN32) || defined (_WIN64) + // Accessing to the serial port under Windows + #include +#endif + +// Include for Linux +#ifdef __linux__ + #include + #include + #include + #include + #include + #include + // File control definitions + #include + #include + #include + #include +#endif + + +/*! To avoid unused parameters */ +#define UNUSED(x) (void)(x) + + +/*! \class serialib + \brief This class is used for communication over a serial device. +*/ +class serialib +{ +public: + + //_____________________________________ + // ::: Constructors and destructors ::: + + + + // Constructor of the class + serialib (); + + // Destructor + ~serialib (); + + + + //_________________________________________ + // ::: Configuration and initialization ::: + + + // Open a device + char openDevice (const char *Device,const unsigned int Bauds); + + // Close the current device + void closeDevice(); + + + + + //___________________________________________ + // ::: Read/Write operation on characters ::: + + + // Write a char + char writeChar (char); + + // Read a char (with timeout) + char readChar (char *pByte,const unsigned int timeOut_ms=0); + + + + + //________________________________________ + // ::: Read/Write operation on strings ::: + + + // Write a string + char writeString (const char *String); + + // Read a string (with timeout) + int readString ( char *receivedString, + char finalChar, + unsigned int maxNbBytes, + const unsigned int timeOut_ms=0); + + + + // _____________________________________ + // ::: Read/Write operation on bytes ::: + + + // Write an array of bytes + int writeBytes (const void *Buffer, const unsigned int NbBytes); + + // Read an array of byte (with timeout) + int readBytes (void *buffer,unsigned int maxNbBytes,const unsigned int timeOut_ms=100, unsigned int sleepDuration_us=100); + + + + + // _________________________ + // ::: Special operation ::: + + + // Empty the received buffer + char flushReceiver(); + + // Return the number of bytes in the received buffer + int available(); + + + + + // _________________________ + // ::: Access to IO bits ::: + + + // Set CTR status (Data Terminal Ready, pin 4) + bool DTR(bool status); + bool setDTR(); + bool clearDTR(); + + // Set RTS status (Request To Send, pin 7) + bool RTS(bool status); + bool setRTS(); + bool clearRTS(); + + // Get RI status (Ring Indicator, pin 9) + bool isRI(); + + // Get DCD status (Data Carrier Detect, pin 1) + bool isDCD(); + + // Get CTS status (Clear To Send, pin 8) + bool isCTS(); + + // Get DSR status (Data Set Ready, pin 9) + bool isDSR(); + + // Get RTS status (Request To Send, pin 7) + bool isRTS(); + + // Get CTR status (Data Terminal Ready, pin 4) + bool isDTR(); + + +private: + // Read a string (no timeout) + int readStringNoTimeOut (char *String,char FinalChar,unsigned int MaxNbBytes); + + // Current DTR and RTS state (can't be read on WIndows) + bool currentStateRTS; + bool currentStateDTR; + + + + + +#if defined (_WIN32) || defined( _WIN64) + // Handle on serial device + HANDLE hSerial; + // For setting serial port timeouts + COMMTIMEOUTS timeouts; +#endif +#ifdef __linux__ + int fd; +#endif + +}; + + + +/*! \class timeOut + \brief This class can manage a timer which is used as a timeout. + */ +// Class timeOut +class timeOut +{ +public: + + // Constructor + timeOut(); + + // Init the timer + void initTimer(); + + // Return the elapsed time since initialization + unsigned long int elapsedTime_ms(); + +private: + // Used to store the previous time (for computing timeout) + struct timeval previousTime; +}; + +#endif // serialib_H diff --git a/feeds/bluetooth-csr/bluez/Makefile b/feeds/bluetooth-csr/bluez/Makefile new file mode 100644 index 000000000..52d06c4a8 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/Makefile @@ -0,0 +1,162 @@ +# +# Copyright (C) 2006-2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=bluez +PKG_VERSION:=5.37 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=@KERNEL/linux/bluetooth/ +PKG_MD5SUM:=33177e5743e24b2b3738f72be64e3ffb + +PKG_LICENSE:=GPL-2.0+ +PKG_LICENSE_FILES:=COPYING +PKG_MAINTAINER:=Nicolas Thill + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/bluez/Default + TITLE:=Bluetooth + URL:=http://www.bluez.org/ +endef + +define Package/bluez-examples +$(call Package/bluez/Default) + SECTION:=utils + CATEGORY:=Utilities + TITLE+= python example apps + DEPENDS:= +endef + +define Package/bluez-examples/description + contains many examples apps for bluetooth, requiring python +endef + +define Package/bluez-libs +$(call Package/bluez/Default) + SECTION:=libs + CATEGORY:=Libraries + TITLE+= library + DEPENDS:=+libpthread +kmod-bluetooth +endef + +define Package/bluez-utils +$(call Package/bluez/Default) + SECTION:=utils + CATEGORY:=Utilities + TITLE+= utilities + DEPENDS:=+bluez-libs +libpthread +librt +glib2 +libncurses +libreadline $(INTL_DEPENDS) $(ICONV_DEPENDS) +endef + +define Package/bluez-daemon +$(call Package/bluez/Default) + SECTION:=utils + CATEGORY:=Utilities + TITLE+= daemon + DEPENDS:=+bluez-libs +bluez-utils +dbus +libical $(INTL_DEPENDS) $(ICONV_DEPENDS) +endef + +define Package/bluez-daemon/conffiles +/etc/bluetooth/main.conf +/etc/bluetooth/network.conf +/etc/bluetooth/input.conf +/etc/bluetooth/proximity.conf +/etc/config/bluetooth +endef + +CONFIGURE_ARGS += \ + --enable-static \ + --enable-shared \ + --enable-client \ + --enable-datafiles \ + --enable-experimental \ + --enable-library \ + --enable-monitor \ + --enable-obex \ + --enable-threads \ + --enable-tools \ + --disable-android \ + --disable-cups \ + --disable-manpages \ + --disable-sixaxis \ + --disable-systemd \ + --disable-test \ + --disable-udev \ + +TARGET_CPPFLAGS += \ + -D_GNU_SOURCE + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/bluetooth $(1)/usr/include/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbluetooth.{a,so*} $(1)/usr/lib/ + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/bluez.pc $(1)/usr/lib/pkgconfig/ +endef + +define Package/bluez-examples/install + $(INSTALL_DIR) $(1)/usr/bin/bluez + $(INSTALL_DATA) $(PKG_BUILD_DIR)/test/* $(1)/usr/bin/bluez/ +endef + +define Package/bluez-libs/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbluetooth.so.* $(1)/usr/lib/ +endef + +define Package/bluez-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_INSTALL_DIR)/usr/bin/bccmd $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/bluemoon $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/btmon $(1)/usr/bin/ + $(CP) $(PKG_BUILD_DIR)/tools/btmgmt $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/ciptool $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/hciattach $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/hciconfig $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/hcidump $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/hcitool $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/hex2hcd $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/l2ping $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/l2test $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/rctest $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/rfcomm $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/sdptool $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/attrib/gatttool $(1)/usr/bin/ +endef + +define Package/bluez-daemon/install + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_INSTALL_DIR)/usr/lib/bluetooth/bluetoothd $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/bin/bluetoothctl $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/bluetooth/obexd $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) ./files/bluetooth.config $(1)/etc/config/bluetooth + $(INSTALL_DIR) $(1)/etc/dbus-1/system.d/ + $(INSTALL_DATA) ./files/bluetooth.dbus $(1)/etc/dbus-1/system.d/bluetooth.conf + $(INSTALL_DIR) $(1)/etc/bluetooth + $(INSTALL_DATA) $(PKG_BUILD_DIR)/src/main.conf $(1)/etc/bluetooth/main.conf + $(INSTALL_DATA) $(PKG_BUILD_DIR)/profiles/network/network.conf $(1)/etc/bluetooth/network.conf + $(INSTALL_DATA) $(PKG_BUILD_DIR)/profiles/input/input.conf $(1)/etc/bluetooth/input.conf + $(INSTALL_DATA) $(PKG_BUILD_DIR)/profiles/proximity/proximity.conf $(1)/etc/bluetooth/proximity.conf + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/bluetoothd.init $(1)/etc/init.d/bluetoothd + $(INSTALL_BIN) ./files/bluez-bccmd.init $(1)/etc/init.d/bluez-bccmd + $(INSTALL_DIR) $(1)/etc/bluetooth + $(INSTALL_DATA) ./files/csr8x11-a12-bt4.2-patch.psr $(1)/etc/bluetooth/ + $(INSTALL_DATA) ./files/csr8x11-coex.psr $(1)/etc/bluetooth/ +endef + +$(eval $(call BuildPackage,bluez-examples)) +$(eval $(call BuildPackage,bluez-libs)) +$(eval $(call BuildPackage,bluez-utils)) +$(eval $(call BuildPackage,bluez-daemon)) diff --git a/feeds/bluetooth-csr/bluez/files/bluetooth.config b/feeds/bluetooth-csr/bluez/files/bluetooth.config new file mode 100644 index 000000000..6f23617a4 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/files/bluetooth.config @@ -0,0 +1,15 @@ +config bluetoothd +# option config /etc/bluetooth/main.conf + option enabled 1 + +config hciattach + option initspeed 115200 + option tty ttyS1 + option type csr + option speed 115200 + option flow noflow + option enabled 0 + +config rfcomm +# option config /etc/bluetooth/rfcomm.conf + option enabled 0 diff --git a/feeds/bluetooth-csr/bluez/files/bluetooth.dbus b/feeds/bluetooth-csr/bluez/files/bluetooth.dbus new file mode 100644 index 000000000..88545fac9 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/files/bluetooth.dbus @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/feeds/bluetooth-csr/bluez/files/bluetoothd.init b/feeds/bluetooth-csr/bluez/files/bluetoothd.init new file mode 100644 index 000000000..75f4d9664 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/files/bluetoothd.init @@ -0,0 +1,13 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2007 OpenWrt.org + +#start after dbus (60) +START=62 +USE_PROCD=1 +PROG=/usr/bin/bluetoothd + +start_service() { + procd_open_instance + procd_set_param command "$PROG" -n + procd_close_instance +} diff --git a/feeds/bluetooth-csr/bluez/files/bluez-bccmd.init b/feeds/bluetooth-csr/bluez/files/bluez-bccmd.init new file mode 100644 index 000000000..d04a66a32 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/files/bluez-bccmd.init @@ -0,0 +1,43 @@ +#!/bin/sh /etc/rc.common +. /lib/ar71xx.sh + +START=63 + +bt_up(){ + hciconfig hci0 up + + count=5 + while [ $count -gt 0 ] + do + if hciconfig hci0 lestates >/dev/null; then + break; + fi + let count=$count-1 + sleep 1 + done + + if [ $count -eq 0 ];then + echo "Failed to enable hci0" >> /tmp/log/bccmd + fi +} + +bccmd_init_csr8x11() { + bt_up + bccmd -t hci -d hci0 psload /etc/bluetooth/csr8x11-a12-bt4.2-patch.psr + bccmd -t hci -d hci0 psload /etc/bluetooth/csr8x11-coex.psr + bccmd -t hci -d hci0 warmreset + bt_up +} + +start() { + board_name=$(ar71xx_board_name) + + case "$board_name" in + cus531mp3|\ + cus531mp3-dual|\ + cus531mp3-nand) + bccmd_init_csr8x11 + ;; + esac +} + diff --git a/feeds/bluetooth-csr/bluez/files/csr8x11-a12-bt4.2-patch.psr b/feeds/bluetooth-csr/bluez/files/csr8x11-a12-bt4.2-patch.psr new file mode 100755 index 000000000..d54e6c905 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/files/csr8x11-a12-bt4.2-patch.psr @@ -0,0 +1,50 @@ +// explicit, PSKEY_HCI_LMP_LOCAL_VERSION (0x010d, 269), 1 words +&010d = 0808 + +// explicit, PSKEY_LMP_REMOTE_VERSION (0x010e, 270), 1 words +&010e = 0008 + +// patch_hardware_0, PSKEY_PATCH50 (0x212c, 8492), 56 words +&212c = 0000 f001 0617 0513 0118 ff2b ff0e 1a00 2818 009e 081b f100 8888 24f0 f925 f821 0a17 0184 0cf0 0117 0013 0009 02a4 fb25 fa21 f915 f811 fb55 fa61 09e0 ff84 10f0 0117 0013 0009 02a4 f935 f841 f925 f821 0f1b 0712 10a4 0494 0712 e151 0722 f915 f811 0018 ff2b ff0e f000 0518 00e2 5a79 + +// patch_hardware_1, PSKEY_PATCH51 (0x212d, 8493), 21 words +&212d = 0002 968a 0863 f925 f821 0757 0663 e099 02ec 05e0 f915 0727 f815 0627 0218 ff2b ff0e 9700 8d18 00e2 7e34 + +// patch_hardware_2, PSKEY_PATCH52 (0x212e, 8494), 16 words +&212e = 0002 0b5a 0100 7834 0040 0327 0223 f815 e311 0218 ff2b ff0e 0b00 5e18 00e2 59c1 + +// patch_hardware_3, PSKEY_PATCH53 (0x212f, 8495), 17 words +&212f = 0000 7315 0084 04f0 0800 0014 03e0 f800 1215 0b27 0018 ff2b ff0e 7300 1818 00e2 0549 + +// patch_hardware_4, PSKEY_PATCH54 (0x2130, 8496), 21 words +&2130 = 0001 53f8 0817 0e27 0c00 6384 07f0 0118 ff2b ff0e 5400 0918 00e2 0917 0118 ff2b ff0e 5400 fb18 00e2 91f6 + +// patch_hardware_5, PSKEY_PATCH55 (0x2131, 8497), 49 words +&2131 = 0002 c0d5 0423 05f4 031b 0012 0280 1df0 021b 0916 1000 00c4 1ef0 0916 03c4 1bf4 031b 0012 0280 17f4 0380 15f4 0480 13f4 0580 11f4 0680 0ff4 0b80 0df4 0d80 0bf4 019c fb00 6719 0d9e 0218 ff2b ff0e c200 8c18 00e2 0218 ff2b ff0e c100 de18 00e2 c5cf + +// patch_hardware_6, PSKEY_PATCH56 (0x2132, 8498), 42 words +&2132 = 0003 243f f40b 0827 0923 e019 0916 01b4 0926 0318 ff2b ff0e 2400 4218 00e2 fa0b 3d14 0327 0114 0227 0014 0127 0027 081b 0816 0218 ff2b ff0e f700 fd18 009e e111 081b 0816 0218 ff2b ff0e 3300 ff18 009e fa0f 40f2 + +// patch_hardware_7, PSKEY_PATCH57 (0x2133, 8499), 23 words +&2133 = 0003 254e 02c0 0916 1000 00c4 02f4 02b0 0916 fec4 e1b1 0922 0816 0318 ff2b ff0e 2500 5218 8000 00c0 08f2 00e2 e402 + +// patch_hardware_8, PSKEY_PATCH58 (0x2134, 8500), 16 words +&2134 = 0003 21ca fa0b 0227 0323 e019 0916 01b4 0926 0318 ff2b ff0e 2200 cd18 00e2 22dc + +// patch_hardware_9, PSKEY_PATCH59 (0x2135, 8501), 18 words +&2135 = 0000 55e2 09f4 0218 ff2b ff0e 2c00 a718 009e 0314 fc0f 0018 ff2b ff0e 5600 0118 00e2 a008 + +// patch_hardware_10, PSKEY_PATCH60 (0x2136, 8502), 30 words +&2136 = 0004 0d80 1aa4 0418 ff2b ff0e 1d00 ba18 009e 0184 0d2c 0013 8f00 89d0 0117 bf00 d6d4 0318 ff2b ff0e 2700 4218 009e 0418 ff2b ff0e 0e00 8418 00e2 6855 + +// patch_hardware_11, PSKEY_PATCH61 (0x2137, 8503), 22 words +&2137 = 0002 4da5 0118 ff2b ff0e 6200 c518 009e 031b 2b22 fcc4 2c26 0114 e700 f025 0218 ff2b ff0e 4e00 a818 00e2 8dfc + +// patch_sched_get_or_peek_message, PSKEY_PATCH123 (0x220b, 8715), 49 words +&220b = fa0b 0717 0484 2cf0 0617 0690 e119 0c00 d438 041a 001a 022b 23f4 0116 0184 20f0 0216 0327 1df4 e119 0016 0784 19f0 e500 ab15 8000 0054 0100 c018 ff2b fe27 0317 ff0e fe9f e199 0cf4 7d00 f214 0127 0014 0027 0317 000e 019f 0014 021b 0226 fa0f 8392 + +// patch_spare1, PSKEY_PATCH155 (0x222b, 8747), 60 words +&222b = e70b 1627 a100 8514 0227 0214 0127 6b00 d814 0427 0214 0327 0417 fe27 0317 ff27 1613 0230 0814 0027 e415 0534 ff0e fe9f 0513 0009 01a4 e015 7fc4 7f84 1bf0 0617 1584 18f0 161b 0116 010e 029f e119 049a 11f4 0116 4184 0ef0 e500 ac11 8000 0050 0100 c014 ff27 fe23 0816 ff0e fe9f 0114 02e0 0014 e70f 4d65 + +// patch_spare2, PSKEY_PATCH156 (0x222c, 8748), 40 words +&222c = f40b 0927 2900 d414 0427 0314 0327 3500 ea14 0627 0314 0527 2900 9614 0827 0414 0727 0917 0110 070e 089f 0917 030e 049f 0617 fe27 0517 ff27 7f14 0027 1514 0127 2a14 0227 0114 0913 ff0e fe9f f40f 3478 diff --git a/feeds/bluetooth-csr/bluez/files/csr8x11-coex.psr b/feeds/bluetooth-csr/bluez/files/csr8x11-coex.psr new file mode 100755 index 000000000..e5f57c19e --- /dev/null +++ b/feeds/bluetooth-csr/bluez/files/csr8x11-coex.psr @@ -0,0 +1,38 @@ +// Set the crystal frequency to 26MHz +&01fe = 6590 + +// PSKEY_COEX_SCHEME +// 7 = Use Unity-e. +&2480 = 0007 + +// Signal Configuration +// -------------------- +// PSKEY_COEX_PIO_UNITY_3_BT_ACTIVE +// BT_ACTIVE (PIO=0, polarity=active high) +&2483 = 0000 0001 + +// PSKEY_COEX_PIO_UNITY_3_BT_STATUS +// BT_STATUS (PIO=5, polarity=active high) +&2484 = 0005 0001 + +// PSKEY_COEX_PIO_UNITY_3_WLAN_DENY +// WLAN_DENY (PIO=1, polarity=active high) +&2485 = 0001 0001 + +// Priority Configuration +// ---------------------- +// PSKEY_coex_transaction_priority_table +&2488 = 0000 0000 0000 0000 0000 0001 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 + +// PSKEY_COEX_BLE_TRANSACTION_PRIORITY_TABLE +&2493 = 0000 0000 0000 0000 0000 0000 0000 0000 0001 0001 0001 0000 0000 0000 0000 0001 + +// PSKEY_COEX_UNITY_EXPRESS_TIMINGS +// BT_ACTIVE lead time - 20 us +// BT_STATUS lead time - 12 us +&248a = 0014 000c + + +//Disable clock request on PIO2 +&0246 = 0000 + diff --git a/feeds/bluetooth-csr/bluez/files/givepin b/feeds/bluetooth-csr/bluez/files/givepin new file mode 100644 index 000000000..e52a3384a --- /dev/null +++ b/feeds/bluetooth-csr/bluez/files/givepin @@ -0,0 +1,14 @@ +#!/bin/sh + +# Write bluetooth PIN number here: +pin= + +if [ -z "$pin" ]; then + msg="Set bluetooth PIN in file $0" + logger -p user.err "$msg" + for i in /dev/pts/* ; do + [ -w $i ] && echo "$msg" > $i + done +else + echo "PIN:$pin" +fi diff --git a/feeds/bluetooth-csr/bluez/patches/200-uart-speed.patch b/feeds/bluetooth-csr/bluez/patches/200-uart-speed.patch new file mode 100644 index 000000000..ebe0153e2 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/patches/200-uart-speed.patch @@ -0,0 +1,40 @@ +--- a/tools/hciattach.c ++++ b/tools/hciattach.c +@@ -101,20 +101,37 @@ int uart_speed(int s) + return B230400; + case 460800: + return B460800; ++/* FIX: Not all platform support this high serial speed ++ claudyus84 @gamil.com ++*/ ++#ifdef B500000 + case 500000: + return B500000; ++#endif ++#ifdef B576000 + case 576000: + return B576000; ++#endif ++#ifdef B921600 + case 921600: + return B921600; ++#endif ++#ifdef B1000000 + case 1000000: + return B1000000; ++#endif ++#ifdef B1152000 + case 1152000: + return B1152000; ++#endif ++#ifdef B1500000 + case 1500000: + return B1500000; ++#endif ++#ifdef B2000000 + case 2000000: + return B2000000; ++#endif + #ifdef B2500000 + case 2500000: + return B2500000; diff --git a/feeds/bluetooth-csr/bluez/patches/201-readline.patch b/feeds/bluetooth-csr/bluez/patches/201-readline.patch new file mode 100644 index 000000000..45e155325 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/patches/201-readline.patch @@ -0,0 +1,48 @@ +--- a/Makefile.in ++++ b/Makefile.in +@@ -2441,7 +2441,7 @@ unit_tests = $(am__append_35) unit/test- + @CLIENT_TRUE@ monitor/uuid.h monitor/uuid.c + + @CLIENT_TRUE@client_bluetoothctl_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@ \ +-@CLIENT_TRUE@ -lreadline ++@CLIENT_TRUE@ -lreadline -lncurses + + @MONITOR_TRUE@monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \ + @MONITOR_TRUE@ monitor/display.h monitor/display.c \ +@@ -2691,13 +2691,13 @@ unit_tests = $(am__append_35) unit/test- + @READLINE_TRUE@ client/display.h + + @READLINE_TRUE@attrib_gatttool_LDADD = lib/libbluetooth-internal.la \ +-@READLINE_TRUE@ src/libshared-glib.la @GLIB_LIBS@ -lreadline ++@READLINE_TRUE@ src/libshared-glib.la @GLIB_LIBS@ -lreadline -lncurses + + @READLINE_TRUE@tools_obex_client_tool_SOURCES = $(gobex_sources) $(btio_sources) \ + @READLINE_TRUE@ tools/obex-client-tool.c + + @READLINE_TRUE@tools_obex_client_tool_LDADD = lib/libbluetooth-internal.la \ +-@READLINE_TRUE@ @GLIB_LIBS@ -lreadline ++@READLINE_TRUE@ @GLIB_LIBS@ -lreadline -lncurses + + @READLINE_TRUE@tools_obex_server_tool_SOURCES = $(gobex_sources) $(btio_sources) \ + @READLINE_TRUE@ tools/obex-server-tool.c +@@ -2707,17 +2707,17 @@ unit_tests = $(am__append_35) unit/test- + @READLINE_TRUE@ client/display.h client/display.c + + @READLINE_TRUE@tools_bluetooth_player_LDADD = gdbus/libgdbus-internal.la \ +-@READLINE_TRUE@ @GLIB_LIBS@ @DBUS_LIBS@ -lreadline ++@READLINE_TRUE@ @GLIB_LIBS@ @DBUS_LIBS@ -lreadline -lncurses + + @READLINE_TRUE@tools_obexctl_SOURCES = tools/obexctl.c \ + @READLINE_TRUE@ client/display.h client/display.c + + @READLINE_TRUE@tools_obexctl_LDADD = gdbus/libgdbus-internal.la \ +-@READLINE_TRUE@ @GLIB_LIBS@ @DBUS_LIBS@ -lreadline ++@READLINE_TRUE@ @GLIB_LIBS@ @DBUS_LIBS@ -lreadline -lncurses + + @READLINE_TRUE@tools_btmgmt_SOURCES = tools/btmgmt.c src/uuid-helper.c client/display.c + @READLINE_TRUE@tools_btmgmt_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la \ +-@READLINE_TRUE@ -lreadline ++@READLINE_TRUE@ -lreadline -lncurses + + @EXPERIMENTAL_TRUE@tools_gatt_service_SOURCES = tools/gatt-service.c + @EXPERIMENTAL_TRUE@tools_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la diff --git a/feeds/bluetooth-csr/bluez/patches/202-fix-unknown-type-a2dp_ldac_t.patch b/feeds/bluetooth-csr/bluez/patches/202-fix-unknown-type-a2dp_ldac_t.patch new file mode 100644 index 000000000..85a4d667c --- /dev/null +++ b/feeds/bluetooth-csr/bluez/patches/202-fix-unknown-type-a2dp_ldac_t.patch @@ -0,0 +1,14 @@ +--- a/profiles/audio/a2dp-codecs.h ++++ b/profiles/audio/a2dp-codecs.h +@@ -234,6 +234,11 @@ typedef struct { + uint8_t channel_mode:4; + } __attribute__ ((packed)) a2dp_aptx_t; + ++typedef struct { ++ a2dp_vendor_codec_t info; ++ uint8_t unknown[2]; ++} __attribute__ ((packed)) a2dp_ldac_t; ++ + #else + #error "Unknown byte order" + #endif diff --git a/feeds/bluetooth-csr/bluez/patches/203-Modify-CSR-pskey-storage-location.patch b/feeds/bluetooth-csr/bluez/patches/203-Modify-CSR-pskey-storage-location.patch new file mode 100644 index 000000000..844d200e8 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/patches/203-Modify-CSR-pskey-storage-location.patch @@ -0,0 +1,14 @@ +--- a/tools/bccmd.c ++++ b/tools/bccmd.c +@@ -48,7 +48,7 @@ + #define CSR_STORES_PSF (0x0002) + #define CSR_STORES_PSROM (0x0004) + #define CSR_STORES_PSRAM (0x0008) +-#define CSR_STORES_DEFAULT (CSR_STORES_PSI | CSR_STORES_PSF) ++#define CSR_STORES_DEFAULT 0 + + #define CSR_TYPE_NULL 0 + #define CSR_TYPE_COMPLEX 1 +-- +2.1.4 + diff --git a/feeds/bluetooth-csr/bluez/patches/204-Add-PIO32-setting-oparation.patch b/feeds/bluetooth-csr/bluez/patches/204-Add-PIO32-setting-oparation.patch new file mode 100755 index 000000000..fa7b577c8 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/patches/204-Add-PIO32-setting-oparation.patch @@ -0,0 +1,93 @@ +diff --git a/tools/bccmd.c b/tools/bccmd.c +old mode 100644 +new mode 100755 +index 6bc28da..1605d1c +--- a/tools/bccmd.c ++++ b/tools/bccmd.c +@@ -636,6 +636,78 @@ static int opt_pskey(int argc, char *argv[], uint16_t *stores, int *reset, int * + return optind; + } + ++int inline serialize_u32(uint8_t *array, uint32_t val32) ++{ ++ if (NULL == array) ++ return -1; ++ ++ array[0] = (val32 & 0xff0000) >> 16; ++ array[1] = val32 >> 24; ++ array[2] = val32 & 0xff; ++ array[3] = (val32 & 0xff00) >> 8; ++ ++ return 0; ++} ++ ++int inline deserialize_u32(uint8_t *array, uint32_t *pval32) ++{ ++ if (NULL == array || NULL == pval32) ++ return -1; ++ ++ *pval32 = (array[1]<<24) ++ | (array[0]<<16) ++ | (array[3]<<8) ++ | array[2]; ++ return 0; ++} ++ ++static int setpio32(int transport, uint32_t varID, uint32_t mask, uint32_t bits) ++{ ++ uint8_t array[32]; ++ uint8_t *ptr = NULL; ++ uint32_t result = 0; ++ int err; ++ ++ memset(array, 0, sizeof(array)); ++ ptr = array; ++ ++ serialize_u32(ptr, mask); ++ ptr += 4; ++ ++ serialize_u32(ptr, bits); ++ ++ err = transport_write(transport, varID, array, 12); ++ if (err < 0) ++ return err; ++ ++ deserialize_u32(&array[8], &result); ++ printf("result: 0x%x\n", result); ++ ++ return 0; ++ ++} ++ ++ ++static int cmd_pio32set(int transport, int argc, char *argv[]) ++{ ++ uint32_t varID; ++ uint32_t mask; ++ uint32_t bits; ++ ++ argc--; ++ argv++; ++ ++ if (3 != argc) ++ return -1; ++ ++ varID = strtol(argv[0] + 2, NULL, 16); ++ mask = strtol(argv[1] + 2, NULL, 16); ++ bits = strtol(argv[2] + 2, NULL, 16); ++ ++ return setpio32(transport, varID, mask, bits); ++} ++ ++ + #define OPT_PSKEY(min, max, stores, reset, help) \ + opt_pskey(argc, argv, (stores), (reset), (help)); \ + argc -= optind; argv += optind; optind = 0; \ +@@ -1112,6 +1184,7 @@ static struct { + { "psread", cmd_psread, NULL, "Read all PS keys" }, + { "psload", cmd_psload, "", "Load all PS keys from PSR file" }, + { "pscheck", cmd_pscheck, "", "Check PSR file" }, ++ { "pio32set", cmd_pio32set, " ","Set value for PIO32 register" }, + { "adc", cmd_adc, "", "Read ADC value of input" }, + { NULL } + }; diff --git a/feeds/bluetooth-csr/bluez/patches/205-Support-full-radio-test.patch b/feeds/bluetooth-csr/bluez/patches/205-Support-full-radio-test.patch new file mode 100755 index 000000000..71313c6f6 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/patches/205-Support-full-radio-test.patch @@ -0,0 +1,50 @@ +diff --git a/tools/bccmd.c b/tools/bccmd.c +index 1605d1c..5655bb5 100755 +--- a/tools/bccmd.c ++++ b/tools/bccmd.c +@@ -555,6 +555,37 @@ static int cmd_radiotest(int transport, int argc, char *argv[]) + return transport_write(transport, CSR_VARID_RADIOTEST, array, 8); + } + ++static int cmd_fullradiotest(int transport, int argc, char *argv[]) ++{ ++ uint8_t array[8]; ++ uint16_t testID; ++ uint16_t word1; ++ uint16_t word2; ++ uint16_t word3; ++ ++ OPT_HELP(4, NULL); ++ ++ testID = atoi(argv[0]); ++ word1 = atoi(argv[1]); ++ word2 = atoi(argv[2]); ++ word3 = atoi(argv[3]); ++ ++ printf("TestID %u, word1 %u, word2 %u, word3 %u\n", ++ testID, word1, word2, word3); ++ ++ memset(array, 0, sizeof(array)); ++ array[0] = testID & 0xff; ++ array[1] = testID >> 8; ++ array[2] = word1 & 0xff; ++ array[3] = word1 >> 8; ++ array[4] = word2 & 0xff; ++ array[5] = word2 >> 8; ++ array[6] = word3 & 0xff; ++ array[7] = word3 >> 8; ++ ++ return transport_write(transport, CSR_VARID_RADIOTEST, array, 8); ++} ++ + static int cmd_memtypes(int transport, int argc, char *argv[]) + { + uint8_t array[8]; +@@ -1176,6 +1207,7 @@ static struct { + { "hoppingon", cmd_hoppingon, "", "Revert to channel hopping" }, + { "rttxdata1", cmd_rttxdata1, " ", "TXData1 radio test" }, + { "radiotest", cmd_radiotest, " ", "Run radio tests" }, ++ { "fullradiotest", cmd_fullradiotest," ", "Run full radio tests" }, + { "memtypes", cmd_memtypes, NULL, "Get memory types" }, + { "psget", cmd_psget, "", "Get value for PS key" }, + { "psset", cmd_psset, " ", "Set value for PS key" }, diff --git a/feeds/bluetooth-csr/bluez/patches/206-Fix-crash-if-uhid-is-not-enabled b/feeds/bluetooth-csr/bluez/patches/206-Fix-crash-if-uhid-is-not-enabled new file mode 100644 index 000000000..0fd15c2c2 --- /dev/null +++ b/feeds/bluetooth-csr/bluez/patches/206-Fix-crash-if-uhid-is-not-enabled @@ -0,0 +1,29 @@ +Index: bluez-5.37/profiles/input/hog.c +=================================================================== +--- bluez-5.37.orig/profiles/input/hog.c ++++ bluez-5.37/profiles/input/hog.c +@@ -107,8 +107,13 @@ static struct hog_device *hog_device_new + product, version); + + dev = new0(struct hog_device, 1); +- dev->device = btd_device_ref(device); + dev->hog = bt_hog_new_default(name, vendor, product, version, prim); ++ if (!dev->hog) { ++ free(dev); ++ return NULL; ++ } ++ ++ dev->device = btd_device_ref(device); + + /* + * TODO: Remove attio callback and use .accept once using +@@ -189,6 +194,9 @@ static int hog_probe(struct btd_service + continue; + + dev = hog_device_new(device, prim); ++ if (!dev) ++ break; ++ + btd_service_set_user_data(service, dev); + return 0; + } diff --git a/feeds/bluetooth-csr/csr8811/Makefile b/feeds/bluetooth-csr/csr8811/Makefile new file mode 100644 index 000000000..176b0e5be --- /dev/null +++ b/feeds/bluetooth-csr/csr8811/Makefile @@ -0,0 +1,29 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=csr8811 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=John Crispin + +include $(INCLUDE_DIR)/package.mk + +define Package/csr8811 + SECTION:=utils + CATEGORY:=Utilities + TITLE:=TIP CSR8811 support package +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Compile/Default + +endef +Build/Compile = $(Build/Compile/Default) + +define Package/csr8811/install + $(CP) ./files/* $(1) +endef + +$(eval $(call BuildPackage,csr8811)) diff --git a/feeds/bluetooth-csr/csr8811/files/etc/init.d/csr8811 b/feeds/bluetooth-csr/csr8811/files/etc/init.d/csr8811 new file mode 100755 index 000000000..1c5bfdb85 --- /dev/null +++ b/feeds/bluetooth-csr/csr8811/files/etc/init.d/csr8811 @@ -0,0 +1,9 @@ +#!/bin/sh /etc/rc.common + +START=80 + +boot() { + bccmd -t bcsp -b 115200 -d /dev/ttyMSM1 psload -r /lib/firmware/CSR8811/pb-207-csr8x11-rev8.psr + sleep 1 + hciattach -s 115200 /dev/ttyMSM1 any 115200 +} diff --git a/feeds/bluetooth-csr/csr8811/files/lib/firmware/CSR8811/pb-207-csr8x11-rev8.psr b/feeds/bluetooth-csr/csr8811/files/lib/firmware/CSR8811/pb-207-csr8x11-rev8.psr new file mode 100644 index 000000000..f8eb9ff90 --- /dev/null +++ b/feeds/bluetooth-csr/csr8811/files/lib/firmware/CSR8811/pb-207-csr8x11-rev8.psr @@ -0,0 +1,320 @@ +// ============================================================================= +// +// Copyright (c) 2015 - 2017 Qualcomm Technologies International, Ltd. +// All Rights Reserved. +// Qualcomm Technologies International, Ltd. Confidential and Proprietary. +// report this in case of problems: +// $Revision: #8 $ +// Built Mon Feb 20 11:33:32 2017 GMT +// Checked-in $DateTime: 2017/02/20 11:36:26 $ +// $File: //depot/bc/gemini-a12/dev/patches/10520/pb-207.psr $ +// +// Patch is for build 10520 gem_5hci_rom_bt4.1_gemA12_1407301204_dspm_encr128 +// +// Issues patched: B-158094, B-169261, B-171616, B-174351, B-176411, +// B-179448, B-180762, B-184008, B-206751, B-208678, +// B-216310, B-220605, B-223811 +// +// Documentation from pb-207.pb +// ---------------------------- +// +// General purpose patch and PSKEY bundle for CSR8811 +// and CSR8311 A12 BT4.2 (build ID 10520). +// +// Documentation from pb-173-common.pb +// ----------------------------------- +// +// General patch bundle for Gemini-A12 (build ID 10520) +// Patches and keys in here should be common to all +// package variants. +// +// Documentation from report_bt4p2.pb +// ---------------------------------- +// +// Issues patched: B-174351 +// +// Report BT version 4.2 +// +// Documentation from patch_ulp_adv_avg_to_calc.xap +// ------------------------------------------------ +// +// Issues patched: B-171616 +// +// BlueCore can be configured through BCCMDVARID_BLE_CONFIG_ADV_RSSI_AVG_PARAM +// to report the advertising rssi average through LE ADVERTISING REPORT to the +// host for a given PEER LE device. +// For more information, See CS-317256-AN. +// +// If the BlueCore is unable to receive a LE ADVERTISING REPORT from the PEER +// before a configured average rssi supervision timeout, then the BlueCore +// should send a LE ADVERTISING REPORT with rssi value equal to -127 conveying +// that the PEER is out of the range; however, it fails to do this. +// +// Documentation from patch_ble_scan_deaf.xap +// ------------------------------------------ +// +// Issues patched: B-158094 +// +// When BlueCore is asked to do BLE scanning, it scans for a window +// approximately 2.5% shorter than asked for. Generally, this does +// not cause noticeable effects; sometimes BLE adverts can be missed +// making connection initialisation between two BLE devices take +// somewhat longer than expected. In pathological cases, especially +// if the scan window is long, connections may fail to be made entirely. +// +// Documentation from patch_usb_suspend_deep_sleep.xap +// --------------------------------------------------- +// +// Issues patched: B-176411 +// +// When BlueCore device is bus powered and is in USB suspend mode, +// the current consumption is approximately 8 mA which is higher +// than the expected current of 250 uA +// +// Documentation from patch_tx_if_reduction.xap +// -------------------------------------------- +// +// Issues patched: B-169261 +// +// When a BlueCore7 device is configured to use a +/-500 kHz transmit IF, this +// can be overridden and a +/-375 kHz IF used instead. This reduces the +// bandwidthof the transmit spectrum providing a greater margin in a Chinese +// regulatory test. +// Only transmit IFs of +/-500 kHz may be reduced; if BlueCore7 is configured to +// use a TX IF of +/-1 MHz IF that will remain unchanged. +// +// Documentation from coex_shutdown.xap +// ------------------------------------ +// +// Issues patched: B-208678 +// +// With Coexistence Unity-3 scheme, If the WLAN_DENY signal is asserted during +// the initial phase of an adaptive frequency hopping(AFH) scan, the Bluecore +// device fails to deassert its BT_ACTIVE signal +// +// Documentation from patch_access_address.xap +// ------------------------------------------- +// +// Issues patched: B-206751 +// +// BlueCore devices may generate access addresses that only +// have one bit transition in the 6 most significant bits. +// The problem is seen on access addresses that have the most +// significant bit set to one and only have one bit transition +// in the 6 most significant bits. +// +// Furthermore, the access address, whilst not identical to the +// advertising channel packets’ Access Address, may differ by +// only one bit. +// +// Documentation from patch_sched_get_or_peek_message.c +// ---------------------------------------------------- +// +// Issues patched: B-220605 +// +// During the crossover of a locally initiated +// LMP_unsniff_req and peer initiated LMP_sniff_subrate_req, +// Bluecore responds with LMP_Sniff_Subrate_Rsp even if it +// has initiated LMP_unsniff. This probably confuses peer and +// peer stops responding, leading to a timeout. +// +// Documentation from patch_sched_get_or_peek_message_part2.c +// ---------------------------------------------------------- +// +// Issues patched: B-220605 +// +// During the crossover of a locally initiated +// LMP_unsniff_req and peer initiated LMP_sniff_subrate_req, +// Bluecore responds with LMP_Sniff_Subrate_Rsp even if it +// has initiated LMP_unsniff. This probably confuses peer and +// peer stops responding, leading to a timeout. +// +// Documentation from patch_ble_advt_restart.xap +// --------------------------------------------- +// +// Issues patched: B-223811 +// +// When advertisements are disabled before the expiry of the interval +// and enabled immediately the advertisements are not sent before the +// expiry of the advertising interval +// +// Documentation from patch_whitelist_connection_status.xap +// -------------------------------------------------------- +// +// Issues patched: B-180762 +// +// If a BlueCore device attempts but fails to form a Low Energy (LE) connection +// to a remote slave using the whitelist, it will make no further attempts to +// initiate a connection to that slave until either the BlueCore is reset or the +// slave is removed and re-added to the whitelist. +// +// Documentation from patch_semp2.xap +// ---------------------------------- +// +// Issues patched: B-184008 +// +// If HCI_SET_EVENT_MASK_PAGE_2 command is sent with wrong parameters +// to Bluecore device, it returns error code +// 'INVALID_HCI_COMMAND_PARAMETERS'. It should return error code +// 'UNKNOWN_HCI_COMMAND'. +// +// Documentation from patch_disc_ll_pdu.xap +// ---------------------------------------- +// +// Issues patched: B-179448 +// +// If a BlueCore device in the Connection State (regardless if in master or +// slave role) receives an unexpected Data Channel PDU from the peer Link Layer +// during the encryption start or encryption pause procedure, it does not exit +// the Connection State and does not notify the Host with error code +// "Connection Terminated Due to MIC Failure (0x3d)". +// +// Documentation from patch_fsm_shared_patchpoint.c +// ------------------------------------------------ +// +// Issues patched: B-216310 +// +// In a particular scenario where the peer device retries a Role Switch +// (after a failed Role Switch) without EPR sequence, the Hydra/BlueCore +// Devices do not handle the user data Start/Stop operation properly. +// As a result the user data does not resume after the procedure is finished. +// +// Version information for input files +// ----------------------------------- +// +// Created by patchmaker.pl Revision: #68 Date: 2016/01/18 +// +// Input file: pb-207.pb +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/pb-207.pb +// File revision: 4 +// +// Input file: pb-173-common.pb +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/pb-173-common.pb +// File revision: 7 +// +// Input file: report_bt4p2.pb +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/report_bt4p2.pb +// File revision: 1 +// +// Input file: patch_ulp_adv_avg_to_calc.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_ulp_adv_avg_to_calc.xap +// File revision: 4 +// +// Input file: ../patch_utils.inc +// Depot file: //depot/bc/gemini-a12/dev/patches/patch_utils.inc +// File revision: 1 +// +// Input file: patch_ble_scan_deaf.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_ble_scan_deaf.xap +// File revision: 3 +// +// Input file: patch_usb_suspend_deep_sleep.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_usb_suspend_deep_sleep.xap +// File revision: 3 +// +// Input file: patch_tx_if_reduction.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_tx_if_reduction.xap +// File revision: 1 +// +// Input file: coex_shutdown.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/coex_shutdown.xap +// File revision: 3 +// +// Input file: patch_access_address.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_access_address.xap +// File revision: 2 +// +// Input file: patch_sched_get_or_peek_message.c +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_sched_get_or_peek_message.c +// File revision: 3 +// +// Input file: patch_sched_get_or_peek_message_part2.c +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_sched_get_or_peek_message_part2.c +// File revision: 2 +// +// Input file: patch_ble_advt_restart.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_ble_advt_restart.xap +// File revision: 2 +// +// Input file: patch_whitelist_connection_status.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_whitelist_connection_status.xap +// File revision: 4 +// +// Input file: patch_semp2.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_semp2.xap +// File revision: 3 +// +// Input file: patch_disc_ll_pdu.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_disc_ll_pdu.xap +// File revision: 4 +// +// Input file: patch_fsm_shared_patchpoint.c +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_fsm_shared_patchpoint.c +// File revision: 3 + +// explicit, PSKEY_HCI_LMP_LOCAL_VERSION (0x010d, 269), 1 words +&010d = 0808 + +// explicit, PSKEY_LMP_REMOTE_VERSION (0x010e, 270), 1 words +&010e = 0008 + +// patch_hardware_0, PSKEY_PATCH50 (0x212c, 8492), 56 words +&212c = 0000 f001 0617 0513 0118 ff2b ff0e 1a00 2818 009e 081b f100 8888 24f0 f925 f821 0a17 0184 0cf0 0117 0013 0009 02a4 fb25 fa21 f915 f811 fb55 fa61 09e0 ff84 10f0 0117 0013 0009 02a4 f935 f841 f925 f821 0f1b 0712 10a4 0494 0712 e151 0722 f915 f811 0018 ff2b ff0e f000 0518 00e2 5a79 + +// patch_hardware_1, PSKEY_PATCH51 (0x212d, 8493), 21 words +&212d = 0002 968a 0863 f925 f821 0757 0663 e099 02ec 05e0 f915 0727 f815 0627 0218 ff2b ff0e 9700 8d18 00e2 7e34 + +// patch_hardware_2, PSKEY_PATCH52 (0x212e, 8494), 16 words +&212e = 0002 0b5a 0100 7834 0040 0327 0223 f815 e311 0218 ff2b ff0e 0b00 5e18 00e2 59c1 + +// patch_hardware_3, PSKEY_PATCH53 (0x212f, 8495), 17 words +&212f = 0000 7315 0084 04f0 0800 0014 03e0 f800 1215 0b27 0018 ff2b ff0e 7300 1818 00e2 0549 + +// patch_hardware_4, PSKEY_PATCH54 (0x2130, 8496), 21 words +&2130 = 0001 53f8 0817 0e27 0c00 6384 07f0 0118 ff2b ff0e 5400 0918 00e2 0917 0118 ff2b ff0e 5400 fb18 00e2 91f6 + +// patch_hardware_5, PSKEY_PATCH55 (0x2131, 8497), 49 words +&2131 = 0002 c0d5 0423 05f4 031b 0012 0280 1df0 021b 0916 1000 00c4 1ef0 0916 03c4 1bf4 031b 0012 0280 17f4 0380 15f4 0480 13f4 0580 11f4 0680 0ff4 0b80 0df4 0d80 0bf4 019c fb00 6719 0d9e 0218 ff2b ff0e c200 8c18 00e2 0218 ff2b ff0e c100 de18 00e2 c5cf + +// patch_hardware_6, PSKEY_PATCH56 (0x2132, 8498), 42 words +&2132 = 0003 243f f40b 0827 0923 e019 0916 01b4 0926 0318 ff2b ff0e 2400 4218 00e2 fa0b 3d14 0327 0114 0227 0014 0127 0027 081b 0816 0218 ff2b ff0e f700 fd18 009e e111 081b 0816 0218 ff2b ff0e 3300 ff18 009e fa0f 40f2 + +// patch_hardware_7, PSKEY_PATCH57 (0x2133, 8499), 23 words +&2133 = 0003 254e 02c0 0916 1000 00c4 02f4 02b0 0916 fec4 e1b1 0922 0816 0318 ff2b ff0e 2500 5218 8000 00c0 08f2 00e2 e402 + +// patch_hardware_8, PSKEY_PATCH58 (0x2134, 8500), 16 words +&2134 = 0003 21ca fa0b 0227 0323 e019 0916 01b4 0926 0318 ff2b ff0e 2200 cd18 00e2 22dc + +// patch_hardware_9, PSKEY_PATCH59 (0x2135, 8501), 18 words +&2135 = 0000 55e2 09f4 0218 ff2b ff0e 2c00 a718 009e 0314 fc0f 0018 ff2b ff0e 5600 0118 00e2 a008 + +// patch_hardware_10, PSKEY_PATCH60 (0x2136, 8502), 30 words +&2136 = 0004 0d80 1aa4 0418 ff2b ff0e 1d00 ba18 009e 0184 0d2c 0013 8f00 89d0 0117 bf00 d6d4 0318 ff2b ff0e 2700 4218 009e 0418 ff2b ff0e 0e00 8418 00e2 6855 + +// patch_hardware_11, PSKEY_PATCH61 (0x2137, 8503), 22 words +&2137 = 0002 4da5 0118 ff2b ff0e 6200 c518 009e 031b 2b22 fcc4 2c26 0114 e700 f025 0218 ff2b ff0e 4e00 a818 00e2 8dfc + +// patch_hardware_12, PSKEY_PATCH62 (0x2138, 8504), 19 words +&2138 = 0002 0f22 0310 081b 0100 8022 0100 b012 04f4 0114 e019 0426 0218 ff2b ff0e 0f00 2618 00e2 bc41 + +// patch_hardware_13, PSKEY_PATCH63 (0x2139, 8505), 12 words +&2139 = 0002 0d95 0513 0100 b022 0218 ff2b ff0e 0f00 db18 00e2 7a40 + +// patch_fsm_shared_patchpoint, PSKEY_PATCH121 (0x2209, 8713), 36 words +&2209 = fc0b 0b13 0717 1d00 c184 1df0 081b 0016 6384 05f0 1380 17f0 0114 13e0 6084 13f0 0100 da80 0df0 0d1b 5d9a 0af4 b900 f014 0127 0214 0027 e315 0010 000e 019f 0014 0d1b 5d26 fc0f a1a6 + +// patch_sched_get_or_peek_message, PSKEY_PATCH123 (0x220b, 8715), 49 words +&220b = fa0b 0717 0484 2cf0 0617 0690 e119 0c00 d438 041a 001a 022b 23f4 0116 0184 20f0 0216 0327 1df4 e119 0016 0784 19f0 e500 ab15 8000 0054 0100 c018 ff2b fe27 0317 ff0e fe9f e199 0cf4 7d00 f214 0127 0014 0027 0317 000e 019f 0014 021b 0226 fa0f 8392 + +// patch_spare1, PSKEY_PATCH155 (0x222b, 8747), 60 words +&222b = e70b 1627 a100 8514 0227 0214 0127 6b00 d814 0427 0214 0327 0417 fe27 0317 ff27 1613 0230 0814 0027 e415 0534 ff0e fe9f 0513 0009 01a4 e015 7fc4 7f84 1bf0 0617 1584 18f0 161b 0116 010e 029f e119 049a 11f4 0116 4184 0ef0 e500 ac11 8000 0050 0100 c014 ff27 fe23 0816 ff0e fe9f 0114 02e0 0014 e70f 4d65 + +// patch_spare2, PSKEY_PATCH156 (0x222c, 8748), 40 words +&222c = f40b 0927 2900 d414 0427 0314 0327 3500 ea14 0627 0314 0527 2900 9614 0827 0414 0727 0917 0110 070e 089f 0917 030e 049f 0617 fe27 0517 ff27 7f14 0027 1514 0127 2a14 0227 0114 0913 ff0e fe9f f40f 3478 +&01fe = 6590 +//Interface, BCSP +//&01f9 = 0001 +//Interface, H4 +&01f9 = 0003 +//Bit rate for 8811, 115200 +&01ea = 0001 c200 diff --git a/feeds/bluetooth/nrf52840/Makefile b/feeds/bluetooth/nrf52840/Makefile new file mode 100644 index 000000000..6a249f1b5 --- /dev/null +++ b/feeds/bluetooth/nrf52840/Makefile @@ -0,0 +1,29 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=nrf52840 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=John Crispin + +include $(INCLUDE_DIR)/package.mk + +define Package/nrf52840 + SECTION:=utils + CATEGORY:=Utilities + TITLE:=TIP NRF52840 support package +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Compile/Default + +endef +Build/Compile = $(Build/Compile/Default) + +define Package/nrf52840/install + $(CP) ./files/* $(1) +endef + +$(eval $(call BuildPackage,nrf52840)) diff --git a/feeds/bluetooth/nrf52840/files/etc/init.d/nrf52840 b/feeds/bluetooth/nrf52840/files/etc/init.d/nrf52840 new file mode 100755 index 000000000..527a59071 --- /dev/null +++ b/feeds/bluetooth/nrf52840/files/etc/init.d/nrf52840 @@ -0,0 +1,19 @@ +#!/bin/sh /etc/rc.common + +START=80 + +boot() { + . /lib/functions/system.sh + case $(board_name) in + edgecore,eap102) + echo 54 > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio54/direction + echo 0 > /sys/class/gpio/gpio54/value + echo 1 > /sys/class/gpio/gpio54/value + btmgmt --index 0 static-addr FF:02:03:04:05:FF + btmgmt --index 0 auto-power + hciconfig hci0 up + hcitool -i hci0 cmd 0x3f 0x006 + ;; + esac +} diff --git a/feeds/bluetooth/nrf52840/files/lib/firmware/CSR8811/pb-207-csr8x11-rev8.psr b/feeds/bluetooth/nrf52840/files/lib/firmware/CSR8811/pb-207-csr8x11-rev8.psr new file mode 100644 index 000000000..f8eb9ff90 --- /dev/null +++ b/feeds/bluetooth/nrf52840/files/lib/firmware/CSR8811/pb-207-csr8x11-rev8.psr @@ -0,0 +1,320 @@ +// ============================================================================= +// +// Copyright (c) 2015 - 2017 Qualcomm Technologies International, Ltd. +// All Rights Reserved. +// Qualcomm Technologies International, Ltd. Confidential and Proprietary. +// report this in case of problems: +// $Revision: #8 $ +// Built Mon Feb 20 11:33:32 2017 GMT +// Checked-in $DateTime: 2017/02/20 11:36:26 $ +// $File: //depot/bc/gemini-a12/dev/patches/10520/pb-207.psr $ +// +// Patch is for build 10520 gem_5hci_rom_bt4.1_gemA12_1407301204_dspm_encr128 +// +// Issues patched: B-158094, B-169261, B-171616, B-174351, B-176411, +// B-179448, B-180762, B-184008, B-206751, B-208678, +// B-216310, B-220605, B-223811 +// +// Documentation from pb-207.pb +// ---------------------------- +// +// General purpose patch and PSKEY bundle for CSR8811 +// and CSR8311 A12 BT4.2 (build ID 10520). +// +// Documentation from pb-173-common.pb +// ----------------------------------- +// +// General patch bundle for Gemini-A12 (build ID 10520) +// Patches and keys in here should be common to all +// package variants. +// +// Documentation from report_bt4p2.pb +// ---------------------------------- +// +// Issues patched: B-174351 +// +// Report BT version 4.2 +// +// Documentation from patch_ulp_adv_avg_to_calc.xap +// ------------------------------------------------ +// +// Issues patched: B-171616 +// +// BlueCore can be configured through BCCMDVARID_BLE_CONFIG_ADV_RSSI_AVG_PARAM +// to report the advertising rssi average through LE ADVERTISING REPORT to the +// host for a given PEER LE device. +// For more information, See CS-317256-AN. +// +// If the BlueCore is unable to receive a LE ADVERTISING REPORT from the PEER +// before a configured average rssi supervision timeout, then the BlueCore +// should send a LE ADVERTISING REPORT with rssi value equal to -127 conveying +// that the PEER is out of the range; however, it fails to do this. +// +// Documentation from patch_ble_scan_deaf.xap +// ------------------------------------------ +// +// Issues patched: B-158094 +// +// When BlueCore is asked to do BLE scanning, it scans for a window +// approximately 2.5% shorter than asked for. Generally, this does +// not cause noticeable effects; sometimes BLE adverts can be missed +// making connection initialisation between two BLE devices take +// somewhat longer than expected. In pathological cases, especially +// if the scan window is long, connections may fail to be made entirely. +// +// Documentation from patch_usb_suspend_deep_sleep.xap +// --------------------------------------------------- +// +// Issues patched: B-176411 +// +// When BlueCore device is bus powered and is in USB suspend mode, +// the current consumption is approximately 8 mA which is higher +// than the expected current of 250 uA +// +// Documentation from patch_tx_if_reduction.xap +// -------------------------------------------- +// +// Issues patched: B-169261 +// +// When a BlueCore7 device is configured to use a +/-500 kHz transmit IF, this +// can be overridden and a +/-375 kHz IF used instead. This reduces the +// bandwidthof the transmit spectrum providing a greater margin in a Chinese +// regulatory test. +// Only transmit IFs of +/-500 kHz may be reduced; if BlueCore7 is configured to +// use a TX IF of +/-1 MHz IF that will remain unchanged. +// +// Documentation from coex_shutdown.xap +// ------------------------------------ +// +// Issues patched: B-208678 +// +// With Coexistence Unity-3 scheme, If the WLAN_DENY signal is asserted during +// the initial phase of an adaptive frequency hopping(AFH) scan, the Bluecore +// device fails to deassert its BT_ACTIVE signal +// +// Documentation from patch_access_address.xap +// ------------------------------------------- +// +// Issues patched: B-206751 +// +// BlueCore devices may generate access addresses that only +// have one bit transition in the 6 most significant bits. +// The problem is seen on access addresses that have the most +// significant bit set to one and only have one bit transition +// in the 6 most significant bits. +// +// Furthermore, the access address, whilst not identical to the +// advertising channel packets’ Access Address, may differ by +// only one bit. +// +// Documentation from patch_sched_get_or_peek_message.c +// ---------------------------------------------------- +// +// Issues patched: B-220605 +// +// During the crossover of a locally initiated +// LMP_unsniff_req and peer initiated LMP_sniff_subrate_req, +// Bluecore responds with LMP_Sniff_Subrate_Rsp even if it +// has initiated LMP_unsniff. This probably confuses peer and +// peer stops responding, leading to a timeout. +// +// Documentation from patch_sched_get_or_peek_message_part2.c +// ---------------------------------------------------------- +// +// Issues patched: B-220605 +// +// During the crossover of a locally initiated +// LMP_unsniff_req and peer initiated LMP_sniff_subrate_req, +// Bluecore responds with LMP_Sniff_Subrate_Rsp even if it +// has initiated LMP_unsniff. This probably confuses peer and +// peer stops responding, leading to a timeout. +// +// Documentation from patch_ble_advt_restart.xap +// --------------------------------------------- +// +// Issues patched: B-223811 +// +// When advertisements are disabled before the expiry of the interval +// and enabled immediately the advertisements are not sent before the +// expiry of the advertising interval +// +// Documentation from patch_whitelist_connection_status.xap +// -------------------------------------------------------- +// +// Issues patched: B-180762 +// +// If a BlueCore device attempts but fails to form a Low Energy (LE) connection +// to a remote slave using the whitelist, it will make no further attempts to +// initiate a connection to that slave until either the BlueCore is reset or the +// slave is removed and re-added to the whitelist. +// +// Documentation from patch_semp2.xap +// ---------------------------------- +// +// Issues patched: B-184008 +// +// If HCI_SET_EVENT_MASK_PAGE_2 command is sent with wrong parameters +// to Bluecore device, it returns error code +// 'INVALID_HCI_COMMAND_PARAMETERS'. It should return error code +// 'UNKNOWN_HCI_COMMAND'. +// +// Documentation from patch_disc_ll_pdu.xap +// ---------------------------------------- +// +// Issues patched: B-179448 +// +// If a BlueCore device in the Connection State (regardless if in master or +// slave role) receives an unexpected Data Channel PDU from the peer Link Layer +// during the encryption start or encryption pause procedure, it does not exit +// the Connection State and does not notify the Host with error code +// "Connection Terminated Due to MIC Failure (0x3d)". +// +// Documentation from patch_fsm_shared_patchpoint.c +// ------------------------------------------------ +// +// Issues patched: B-216310 +// +// In a particular scenario where the peer device retries a Role Switch +// (after a failed Role Switch) without EPR sequence, the Hydra/BlueCore +// Devices do not handle the user data Start/Stop operation properly. +// As a result the user data does not resume after the procedure is finished. +// +// Version information for input files +// ----------------------------------- +// +// Created by patchmaker.pl Revision: #68 Date: 2016/01/18 +// +// Input file: pb-207.pb +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/pb-207.pb +// File revision: 4 +// +// Input file: pb-173-common.pb +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/pb-173-common.pb +// File revision: 7 +// +// Input file: report_bt4p2.pb +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/report_bt4p2.pb +// File revision: 1 +// +// Input file: patch_ulp_adv_avg_to_calc.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_ulp_adv_avg_to_calc.xap +// File revision: 4 +// +// Input file: ../patch_utils.inc +// Depot file: //depot/bc/gemini-a12/dev/patches/patch_utils.inc +// File revision: 1 +// +// Input file: patch_ble_scan_deaf.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_ble_scan_deaf.xap +// File revision: 3 +// +// Input file: patch_usb_suspend_deep_sleep.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_usb_suspend_deep_sleep.xap +// File revision: 3 +// +// Input file: patch_tx_if_reduction.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_tx_if_reduction.xap +// File revision: 1 +// +// Input file: coex_shutdown.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/coex_shutdown.xap +// File revision: 3 +// +// Input file: patch_access_address.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_access_address.xap +// File revision: 2 +// +// Input file: patch_sched_get_or_peek_message.c +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_sched_get_or_peek_message.c +// File revision: 3 +// +// Input file: patch_sched_get_or_peek_message_part2.c +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_sched_get_or_peek_message_part2.c +// File revision: 2 +// +// Input file: patch_ble_advt_restart.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_ble_advt_restart.xap +// File revision: 2 +// +// Input file: patch_whitelist_connection_status.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_whitelist_connection_status.xap +// File revision: 4 +// +// Input file: patch_semp2.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_semp2.xap +// File revision: 3 +// +// Input file: patch_disc_ll_pdu.xap +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_disc_ll_pdu.xap +// File revision: 4 +// +// Input file: patch_fsm_shared_patchpoint.c +// Depot file: //depot/bc/gemini-a12/dev/patches/10520/patch_fsm_shared_patchpoint.c +// File revision: 3 + +// explicit, PSKEY_HCI_LMP_LOCAL_VERSION (0x010d, 269), 1 words +&010d = 0808 + +// explicit, PSKEY_LMP_REMOTE_VERSION (0x010e, 270), 1 words +&010e = 0008 + +// patch_hardware_0, PSKEY_PATCH50 (0x212c, 8492), 56 words +&212c = 0000 f001 0617 0513 0118 ff2b ff0e 1a00 2818 009e 081b f100 8888 24f0 f925 f821 0a17 0184 0cf0 0117 0013 0009 02a4 fb25 fa21 f915 f811 fb55 fa61 09e0 ff84 10f0 0117 0013 0009 02a4 f935 f841 f925 f821 0f1b 0712 10a4 0494 0712 e151 0722 f915 f811 0018 ff2b ff0e f000 0518 00e2 5a79 + +// patch_hardware_1, PSKEY_PATCH51 (0x212d, 8493), 21 words +&212d = 0002 968a 0863 f925 f821 0757 0663 e099 02ec 05e0 f915 0727 f815 0627 0218 ff2b ff0e 9700 8d18 00e2 7e34 + +// patch_hardware_2, PSKEY_PATCH52 (0x212e, 8494), 16 words +&212e = 0002 0b5a 0100 7834 0040 0327 0223 f815 e311 0218 ff2b ff0e 0b00 5e18 00e2 59c1 + +// patch_hardware_3, PSKEY_PATCH53 (0x212f, 8495), 17 words +&212f = 0000 7315 0084 04f0 0800 0014 03e0 f800 1215 0b27 0018 ff2b ff0e 7300 1818 00e2 0549 + +// patch_hardware_4, PSKEY_PATCH54 (0x2130, 8496), 21 words +&2130 = 0001 53f8 0817 0e27 0c00 6384 07f0 0118 ff2b ff0e 5400 0918 00e2 0917 0118 ff2b ff0e 5400 fb18 00e2 91f6 + +// patch_hardware_5, PSKEY_PATCH55 (0x2131, 8497), 49 words +&2131 = 0002 c0d5 0423 05f4 031b 0012 0280 1df0 021b 0916 1000 00c4 1ef0 0916 03c4 1bf4 031b 0012 0280 17f4 0380 15f4 0480 13f4 0580 11f4 0680 0ff4 0b80 0df4 0d80 0bf4 019c fb00 6719 0d9e 0218 ff2b ff0e c200 8c18 00e2 0218 ff2b ff0e c100 de18 00e2 c5cf + +// patch_hardware_6, PSKEY_PATCH56 (0x2132, 8498), 42 words +&2132 = 0003 243f f40b 0827 0923 e019 0916 01b4 0926 0318 ff2b ff0e 2400 4218 00e2 fa0b 3d14 0327 0114 0227 0014 0127 0027 081b 0816 0218 ff2b ff0e f700 fd18 009e e111 081b 0816 0218 ff2b ff0e 3300 ff18 009e fa0f 40f2 + +// patch_hardware_7, PSKEY_PATCH57 (0x2133, 8499), 23 words +&2133 = 0003 254e 02c0 0916 1000 00c4 02f4 02b0 0916 fec4 e1b1 0922 0816 0318 ff2b ff0e 2500 5218 8000 00c0 08f2 00e2 e402 + +// patch_hardware_8, PSKEY_PATCH58 (0x2134, 8500), 16 words +&2134 = 0003 21ca fa0b 0227 0323 e019 0916 01b4 0926 0318 ff2b ff0e 2200 cd18 00e2 22dc + +// patch_hardware_9, PSKEY_PATCH59 (0x2135, 8501), 18 words +&2135 = 0000 55e2 09f4 0218 ff2b ff0e 2c00 a718 009e 0314 fc0f 0018 ff2b ff0e 5600 0118 00e2 a008 + +// patch_hardware_10, PSKEY_PATCH60 (0x2136, 8502), 30 words +&2136 = 0004 0d80 1aa4 0418 ff2b ff0e 1d00 ba18 009e 0184 0d2c 0013 8f00 89d0 0117 bf00 d6d4 0318 ff2b ff0e 2700 4218 009e 0418 ff2b ff0e 0e00 8418 00e2 6855 + +// patch_hardware_11, PSKEY_PATCH61 (0x2137, 8503), 22 words +&2137 = 0002 4da5 0118 ff2b ff0e 6200 c518 009e 031b 2b22 fcc4 2c26 0114 e700 f025 0218 ff2b ff0e 4e00 a818 00e2 8dfc + +// patch_hardware_12, PSKEY_PATCH62 (0x2138, 8504), 19 words +&2138 = 0002 0f22 0310 081b 0100 8022 0100 b012 04f4 0114 e019 0426 0218 ff2b ff0e 0f00 2618 00e2 bc41 + +// patch_hardware_13, PSKEY_PATCH63 (0x2139, 8505), 12 words +&2139 = 0002 0d95 0513 0100 b022 0218 ff2b ff0e 0f00 db18 00e2 7a40 + +// patch_fsm_shared_patchpoint, PSKEY_PATCH121 (0x2209, 8713), 36 words +&2209 = fc0b 0b13 0717 1d00 c184 1df0 081b 0016 6384 05f0 1380 17f0 0114 13e0 6084 13f0 0100 da80 0df0 0d1b 5d9a 0af4 b900 f014 0127 0214 0027 e315 0010 000e 019f 0014 0d1b 5d26 fc0f a1a6 + +// patch_sched_get_or_peek_message, PSKEY_PATCH123 (0x220b, 8715), 49 words +&220b = fa0b 0717 0484 2cf0 0617 0690 e119 0c00 d438 041a 001a 022b 23f4 0116 0184 20f0 0216 0327 1df4 e119 0016 0784 19f0 e500 ab15 8000 0054 0100 c018 ff2b fe27 0317 ff0e fe9f e199 0cf4 7d00 f214 0127 0014 0027 0317 000e 019f 0014 021b 0226 fa0f 8392 + +// patch_spare1, PSKEY_PATCH155 (0x222b, 8747), 60 words +&222b = e70b 1627 a100 8514 0227 0214 0127 6b00 d814 0427 0214 0327 0417 fe27 0317 ff27 1613 0230 0814 0027 e415 0534 ff0e fe9f 0513 0009 01a4 e015 7fc4 7f84 1bf0 0617 1584 18f0 161b 0116 010e 029f e119 049a 11f4 0116 4184 0ef0 e500 ac11 8000 0050 0100 c014 ff27 fe23 0816 ff0e fe9f 0114 02e0 0014 e70f 4d65 + +// patch_spare2, PSKEY_PATCH156 (0x222c, 8748), 40 words +&222c = f40b 0927 2900 d414 0427 0314 0327 3500 ea14 0627 0314 0527 2900 9614 0827 0414 0727 0917 0110 070e 089f 0917 030e 049f 0617 fe27 0517 ff27 7f14 0027 1514 0127 2a14 0227 0114 0913 ff0e fe9f f40f 3478 +&01fe = 6590 +//Interface, BCSP +//&01f9 = 0001 +//Interface, H4 +&01f9 = 0003 +//Bit rate for 8811, 115200 +&01ea = 0001 c200 diff --git a/profiles/edgecore_eap101.yml b/profiles/edgecore_eap101.yml index 8baa075d7..76d2891a4 100644 --- a/profiles/edgecore_eap101.yml +++ b/profiles/edgecore_eap101.yml @@ -7,12 +7,13 @@ image: bin/targets/ipq807x/ipq60xx/openwrt-ipq807x-edgecore_eap101-squashfs-sysu feeds: - name: ipq807x path: ../../feeds/ipq807x + - name: bluetooth_cc2652 + path: ../../feeds/bluetooth-cc2652 include: - wifi-ax - ucentral-ap packages: - - kmod-bluetooth - - bluez-libs - - bluez-daemon - - bluez-utils - - usbutils + - cc2652 +diffconfig: | + CONFIG_BUSYBOX_CUSTOM=y + CONFIG_BUSYBOX_CONFIG_STTY=y diff --git a/profiles/edgecore_eap102.yml b/profiles/edgecore_eap102.yml index e5f2b73bb..9488fec38 100644 --- a/profiles/edgecore_eap102.yml +++ b/profiles/edgecore_eap102.yml @@ -7,15 +7,16 @@ image: bin/targets/ipq807x/ipq807x/openwrt-ipq807x-edgecore_eap102-squashfs-sysu feeds: - name: ipq807x path: ../../feeds/ipq807x + - name: bluetooth + path: ../../feeds/bluetooth include: - wifi-ax - ucentral-ap packages: + - nrf52840 - kmod-bluetooth - - kmod-bluetooth_6lowpan - bluez-libs - - bluez-daemon - bluez-utils - - usbutils + - bluez-utils-extra diffconfig: | CONFIG_KERNEL_IPQ_MEM_PROFILE=0 diff --git a/profiles/edgecore_eap106.yml b/profiles/edgecore_eap106.yml index a6e003937..8184c6542 100644 --- a/profiles/edgecore_eap106.yml +++ b/profiles/edgecore_eap106.yml @@ -7,15 +7,15 @@ image: bin/targets/ipq807x/ipq807x/openwrt-ipq807x-edgecore_eap106-squashfs-sysu feeds: - name: ipq807x path: ../../feeds/ipq807x + - name: bluetooth_csr + path: ../../feeds/bluetooth-csr include: - wifi-ax - ucentral-ap packages: + - csr8811 - kmod-bluetooth - - kmod-bluetooth_6lowpan - bluez-libs - - bluez-daemon - bluez-utils - - usbutils diffconfig: | CONFIG_KERNEL_IPQ_MEM_PROFILE=0