Skip to content
Snippets Groups Projects
ble.c 6.95 KiB
Newer Older
#include "epicardium.h"
#include "modules/log.h"

#include "fs_util.h"
#include "wsf_types.h"
#include "wsf_buf.h"
#include "wsf_trace.h"
schneider's avatar
schneider committed
#include "ble_api.h"
#include "hci_vs.h"
#include "att_api.h"
#include "trng.h"
#include "FreeRTOS.h"
#include "timers.h"

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

schneider's avatar
schneider committed
#define WSF_BUF_POOLS 6
#define WSF_BUF_SIZE 0x1048
schneider's avatar
schneider committed
uint32_t SystemHeapSize = WSF_BUF_SIZE;
uint32_t SystemHeap[WSF_BUF_SIZE / 4];
uint32_t SystemHeapStart;
/* Task ID for the ble handler */
static TaskHandle_t ble_task_id = NULL;

/*! Default pool descriptor. */
schneider's avatar
schneider committed
/* clang-format off */
static wsfBufPoolDesc_t mainPoolDesc[WSF_BUF_POOLS] =
{
  {  16,  8 },
  {  32,  4 },
  {  64,  4 },
  { 128,  4 },
  { 256,  4 },
  { 512,  4 }
schneider's avatar
schneider committed
/* clang-format on */

static StaticTimer_t x;
static TimerHandle_t timerWakeup = NULL;
static int lasttick              = 0;
/*! \brief  Stack initialization for app. */
extern void StackInit(void);
extern void AppInit(void);
extern void bleuart_init(void);
extern void bleFileTransfer_init(void);
extern void bleCard10_init(void);
extern void BbBleDrvSetTxPower(int8_t power);
/*************************************************************************************************/
void PalSysAssertTrap(void)
schneider's avatar
schneider committed
	while (1) {
	}
/*************************************************************************************************/
static bool_t myTrace(const uint8_t *pBuf, uint32_t len)
schneider's avatar
schneider committed
	extern uint8_t wsfCsNesting;
schneider's avatar
schneider committed
	if (wsfCsNesting == 0) {
		fwrite(pBuf, len, 1, stdout);
		return TRUE;
	}
schneider's avatar
schneider committed
	return FALSE;
/*************************************************************************************************/
static void WsfInit(void)
{
	uint32_t bytesUsed __attribute__((unused));
schneider's avatar
schneider committed
	WsfTimerInit();

	SystemHeapStart = (uint32_t)&SystemHeap;
	memset(SystemHeap, 0, sizeof(SystemHeap));
	//printf("SystemHeapStart = 0x%x\n", SystemHeapStart);
	//printf("SystemHeapSize = 0x%x\n", SystemHeapSize);

	WsfTraceRegisterHandler(myTrace);
	WsfTraceEnable(TRUE);

	bytesUsed = WsfBufInit(WSF_BUF_POOLS, mainPoolDesc);
	APP_TRACE_INFO1("bytesUsed = %u", (unsigned int)bytesUsed);
schneider's avatar
schneider committed
/*************************************************************************************************/
/* TODO: We need a source of MACs */
static void setAddress(void)
schneider's avatar
schneider committed
	uint8_t bdAddr[6] = { 0x02, 0x02, 0x44, 0x8B, 0x05, 0x00 };
	char buf[32];

	int result = fs_read_text_file("mac.txt", buf, sizeof(buf));

	if (result == -1) {
		APP_TRACE_INFO0("mac.txt not found, generating random MAC");
		bdAddr[0] = 0xCA;
		bdAddr[1] = 0x4D;
		bdAddr[2] = 0x10;
		TRNG_Read(MXC_TRNG, bdAddr + 3, 3);
		sprintf(buf,
			"%02x:%02x:%02x:%02x:%02x:%02x\n",
			bdAddr[0],
			bdAddr[1],
			bdAddr[2],
			bdAddr[3],
			bdAddr[4],
			bdAddr[5]);
		fs_write_file("mac.txt", buf, strlen(buf));
	} else {
		APP_TRACE_INFO1("mac file contents: %s", buf);
	}

schneider's avatar
schneider committed
	int a, b, c, d, e, f;
	if (sscanf(buf, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f) == 6) {
		bdAddr[0] = f;
		bdAddr[1] = e;
		bdAddr[2] = d;
		bdAddr[3] = c;
		bdAddr[4] = b;
		bdAddr[5] = a;
	}

	LOG_INFO(
		"ble",
		"Setting MAC address to %02X:%02X:%02X:%02X:%02X:%02X",
		bdAddr[5],
		bdAddr[4],
		bdAddr[3],
		bdAddr[2],
		bdAddr[1],
		bdAddr[0]
	);
schneider's avatar
schneider committed
	HciVsSetBdAddr(bdAddr);
schneider's avatar
schneider committed
/*************************************************************************************************/
static void vTimerCallback(xTimerHandle pxTimer)
schneider's avatar
schneider committed
	//printf("wake\n");
	int tick = xTaskGetTickCount();
	//printf("WsfTimerUpdate(%d)\n", tick - lasttick);
	WsfTimerUpdate(tick - lasttick);
	lasttick = tick;
	//printf("done\n");
schneider's avatar
schneider committed
/*************************************************************************************************/
static void notify(void)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
schneider's avatar
schneider committed
	if (xPortIsInsideInterrupt()) {
		vTaskNotifyGiveFromISR(ble_task_id, &xHigherPriorityTaskWoken);
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	} else {
		xTaskNotifyGive(ble_task_id);
	}
schneider's avatar
schneider committed
/*************************************************************************************************/
void WsfTimerNotify(void)
{
schneider's avatar
schneider committed
	//printf("WsfTimerNotify\n");
	// TODO: Can we do this without waking up the task?
	// xTimerChangePeriodFromISR exists
	notify();
schneider's avatar
schneider committed
/*************************************************************************************************/
void wsf_ble_signal_event(void)
{
schneider's avatar
schneider committed
	//printf("wsf_ble_signal_event\n");
	notify();
schneider's avatar
schneider committed
/*************************************************************************************************/
#define BLEMAXCFGBYTES 100
bool ble_shall_start(void)
{
	int bleConfigFile = epic_file_open("ble.txt", "r");
	if (bleConfigFile < 0) {
		LOG_INFO("ble", "can not open ble.txt -> BLE is not started");
		epic_file_close(bleConfigFile);
		return false;
	}

	char cfgBuf[BLEMAXCFGBYTES + 1];
	int readNum = epic_file_read(bleConfigFile, cfgBuf, BLEMAXCFGBYTES);
	epic_file_close(bleConfigFile);
	if (readNum < 0) {
		LOG_WARN("ble", "can not read ble.txt -> BLE is not started");
		return false;
	}
	cfgBuf[readNum] = '\0';

	char bleActiveStr[]              = "active=true";
	cfgBuf[sizeof(bleActiveStr) - 1] = '\0';

	if (strcmp(cfgBuf, "active=true") != 0) {
		LOG_INFO("ble", "BLE is disabled.");
		return false;
	} else {
		LOG_INFO("ble", "BLE is enabled.");
		return true;
	}
}
/*************************************************************************************************/
static void scheduleTimer(void)
schneider's avatar
schneider committed
	bool_t timerRunning;
	wsfTimerTicks_t time_to_next_expire;

	vTimerCallback(NULL);
	time_to_next_expire = WsfTimerNextExpiration(&timerRunning);

	if (timerRunning) {
		//printf("time_to_next_expire = %d\n", time_to_next_expire);
		//printf("change period\n");
		/* We need to make sure not to schedule a 0 ticks timer.
		 * Maybe it would also be enough to simply call the dispatcher
		 * in this case... */
		if (time_to_next_expire == 0) {
			time_to_next_expire = 1;
		}

schneider's avatar
schneider committed
		if (timerWakeup != NULL) {
			xTimerChangePeriod(
				timerWakeup,
				pdMS_TO_TICKS(time_to_next_expire),
				0
			);
			//printf("insert done\n");
		} else {
			LOG_ERR("ble", "Could not create timer");
schneider's avatar
schneider committed
		}
	} else {
		APP_TRACE_INFO0("No timer running");
schneider's avatar
schneider committed
/*************************************************************************************************/
void vBleTask(void *pvParameters)
	ble_task_id = xTaskGetCurrentTaskHandle();

	/*
	 * Delay BLE startup by a bit because it locks up Epicardium otherwise.
	 */
	vTaskDelay(pdMS_TO_TICKS(500));

schneider's avatar
schneider committed
	WsfInit();
	StackInit();
	BbBleDrvSetTxPower(0);
schneider's avatar
schneider committed
	setAddress();

	NVIC_SetPriority(BTLE_SFD_TO_IRQn, 2);
	NVIC_SetPriority(BTLE_TX_DONE_IRQn, 2);
	NVIC_SetPriority(BTLE_RX_RCVD_IRQn, 2);
	AppInit();
	BleStart();
	AttsDynInit();

	bleuart_init();
	bleFileTransfer_init();
schneider's avatar
schneider committed

	lasttick = xTaskGetTickCount();

	timerWakeup = xTimerCreateStatic(
		"timerWakeup",    /* name */
		pdMS_TO_TICKS(1), /* period/time */
		pdFALSE,          /* auto reload */
		NULL,             /* timer ID */
		vTimerCallback,
		&x); /* callback */

	while (1) {
		ulTaskNotifyTake(pdTRUE, portTICK_PERIOD_MS * 1000);
schneider's avatar
schneider committed
		wsfOsDispatcher();
		scheduleTimer();
	}