I have written a word (32 bites) in 0xFF000 using nrf_fstorage_write(), When BLEInit(), nrf_fstorage_evt() callback not trigged,
BLE_Sleept()
nrf_storage_write()
BLE_wakeup()
I have written a word (32 bites) in 0xFF000 using nrf_fstorage_write(), When BLEInit(), nrf_fstorage_evt() callback not trigged,
BLE_Sleept()
nrf_storage_write()
BLE_wakeup()
Sorry for the delay, Thank you for your reply. I have changed the code as follows:
nrf_fstorage_api_t * p_fs_api;
p_fs_api = &nrf_fstorage_nvmc; -- I have changed to p_fs_api = &nrf_fstorage_sd;
iDebug("fs Init started.");
nrf_fstorage_init(&my_instance,/*fstorage instance,previously defined. */
p_fs_api, /* Name of the backend. */
NULL /* Optional parameter, backend-dependant. */
);But I could not see any improvement.
Can you share , if i have missed any point that you have given
I cannot tell what the program flow is based on the code snippet you posted. Can you upload a minimal version of your project so I can try to run it here?
But I could not see any improvement.
Have you performed any debugging to see if the program gets stuck or crashes?
Hello,
This is my code as follows:
#include "Infa.h"
#define IMG_SIZE 16 //4096
#define IMG_SIZE1 4 //4096
__ALIGN(32) uint8_t img[4] = {12,13,14,15};
__ALIGN(32) uint8_t img1[4] = {15,16,17,18};
__ALIGN(32) uint8_t img_copy[IMG_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
#define FLASH_START_ADDR 0xFF000//0x30000 //0x10001000 //0x3F000 //0x30000
#define FLASH_START_ADDR1 0xFF000 //0x10001000 //0x3F000 //0x30000
#define FLASH_START_ADDR2 0xFF008
bool write_finished = false, erase_finished = false;
void callback(nrf_fstorage_evt_t *p_evt)
{
iDebug("======> flash result event");
/*if (p_evt->id == FDS_EVT_INIT) {
iDebug("======> flash write result event");
write_finished = true;
} */
if (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) {
iDebug("======> flash write result event");
write_finished = true;
}
if (p_evt->id == NRF_FSTORAGE_EVT_ERASE_RESULT) {
iDebug("======> erase write result event");
erase_finished = true;
}
}
NRF_FSTORAGE_DEF(nrf_fstorage_t my_instance) = {
.evt_handler = callback,
.start_addr = FLASH_START_ADDR,
.end_addr = 0xFFFFF , //FLASH_START_ADDR + 32, //0x3ffff-1, // 10,
};
bool write_to_flash(int SAddr)
{
ret_code_t rc=0;
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
if(SAddr==1){
rc = nrf_fstorage_write(&my_instance, /* The instance to use. */
FLASH_START_ADDR1, /* The address in flash where to store the data. */
img, /* A pointer to the data. */
IMG_SIZE1, /* IMG_SIZE, Lenght of the data, in bytes. */
NULL /* Optional parameter, backend-dependent. */
);
}
else if(SAddr==2){
rc = nrf_fstorage_write(&my_instance, /* The instance to use. */
FLASH_START_ADDR2, /* The address in flash where to store the data. */
img1, /* A pointer to the data. */
IMG_SIZE1, /* IMG_SIZE, Lenght of the data, in bytes. */
NULL /* Optional parameter, backend-dependent. */
);
}
app_sched_execute();
// nrf_delay_ms(1000);
iDebug("\r\nflash write.... \r\n");
while(nrf_fstorage_is_busy(&my_instance));
if (rc == NRF_SUCCESS) {
iDebug("\r\nflash write success");
return true;
} else {
iDebug("\r\nflash write failure");
return false;
}
}
bool read_from_flash(int rType)
{
ret_code_t rc = 0;
if(rType==1){
rc = nrf_fstorage_read(&my_instance, /* The instance to use. */
FLASH_START_ADDR1, /* The address in flash where to read data from. */
img_copy, /* A buffer to copy the data into. */
4 /* Lenght of the data, in bytes. */
);
}
else if(rType==2){
rc = nrf_fstorage_read(&my_instance, /* The instance to use. */
FLASH_START_ADDR2, /* The address in flash where to read data from. */
img_copy, /* A buffer to copy the data into. */
4 /* Lenght of the data, in bytes. */
);
}
if (rc == NRF_SUCCESS) {
//iDebug("\r\nflash read success - Size %d",IMG_SIZE);
for (int i = 0; i < 4; i++) {
iDebug("\r\nflash read [%d] = %d", i,img_copy[i]);
//if (img[i] != img_copy[i]) {
// iDebug("\r\nflash read unequal at index %d", i);
// return false;
// }
}
return true;
} else {
iDebug("\r\nflash read Not success");
return false;
}
}
bool erase_from_flash()
{
iDebug("flash erase start..");
ret_code_t rc = nrf_fstorage_erase(&my_instance,/* The instance to use. */
FLASH_START_ADDR, /* The address of the flash pages to erase. */
1, /* The number of pages to erase. */
NULL /* Optional parameter, backend-dependent. */
);
app_sched_execute();
while(nrf_fstorage_is_busy(&my_instance));
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
if (rc == NRF_SUCCESS) {
iDebug("flash erase success");
return true;
} else {
iDebug("flash erase failure %u" + rc );
return false;
}
}
//======================= TWI - DIO ====================================
/* TWI instance ID. */
#if TWI0_ENABLED
#define TWI_INSTANCE_ID 0
#elif TWI1_ENABLED
#define TWI_INSTANCE_ID 1
#endif
/* Number of possible TWI addresses. */
#define TWI_ADDRESSES 127
/* Common addresses definition for temperature sensor. */
#define MAX5805_ADDR (0x18)
#define MAX5805_REG_REF_CMD 0x50U
#define MAX5805_REG_REF_HI 0x00U
#define MAX5805_REG_REF_LO 0x38U
#define MAX5805_REG_POW_CMD 0x40U
#define MAX5805_REG_POW_HI 0x00U
#define MAX5805_REG_POW_LO 0x00U
#define MAX5805_REG_CODELODE_CMD 0xB0U //0xA0U //0xB0U
#define MAX5805_REG_CODELODE_HI 0x00 //0x08//0xFFU
#define MAX5805_REG_CODELODE_LO 0x00 //0x00//0xF0U
#define MAX5805_REG_CONF 0x01U
#define MAX5805_REG_POWER 0x02U
/* Mode for LM75B. */
#define NORMAL_MODE 0U
#define SDA_PIN NRF_GPIO_PIN_MAP(0, 21)
#define SCL_PIN NRF_GPIO_PIN_MAP(0, 23)
/* Indicates if operation on TWI has ended. */
static volatile bool m_xfer_done = false;
/* Buffer for samples read from temperature sensor. */
static uint8_t m_sample;
/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);
//static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(0);
//=====================================================================
/**Global variable declaration***/
bool GetCurrentValue, PeriodicRead,GetModbusValue,SendMode;
TransportMode_t IncomingTransportMode;
uint16_t ModDataLen,ModStartAddr;
uint16_t CalibValue4mA,CalibValue20mA,ProcessValue4mA,ProcessValue20mA;
/*******************************/
static void read_sensor_data()
{
m_xfer_done = false;
/* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
ret_code_t err_code = nrf_drv_twi_rx(&m_twi, MAX5805_ADDR, &m_sample, sizeof(m_sample));
uint8_t lenData= sizeof(m_sample);
iDebug("%d -- %d,%d", m_sample,lenData,err_code);
//APP_ERROR_CHECK(err_code);
}
/**
* @brief Function for setting active mode on MMA7660 accelerometer.
*/
void MAX5805_set_mode(void)
{
ret_code_t err_code;
/* Writing to LM75B_REG_CONF "0" set temperature sensor in NORMAL mode. */
//uint8_t reg[2] = {LM75B_REG_CONF, NORMAL_MODE};
uint8_t reg[3] = {MAX5805_REG_CODELODE_CMD,MAX5805_REG_CODELODE_HI,MAX5805_REG_CODELODE_LO};
//iDebug("MAX5805_set_mode 1 " );
err_code = nrf_drv_twi_tx(&m_twi, MAX5805_ADDR, reg, sizeof(reg), false);
//iDebug("MAX5805_set_mode 1 %d" ,err_code);
//APP_ERROR_CHECK(err_code);
if(err_code) {}
while (m_xfer_done == false);
/* Writing to pointer byte. */
/* reg[0] = LM75B_REG_TEMP;
m_xfer_done = false;
err_code = nrf_drv_twi_tx(&m_twi, MAX5805_ADDR, reg, 1, false);
APP_ERROR_CHECK(err_code);
while (m_xfer_done == false); */
iDebug("MAX5805_set_mode Write Success");
//uint8_t i=0;
//if(i)
read_sensor_data();
}
/**
* @brief Function for handling data from temperature sensor.
*
* @param[in] temp Temperature in Celsius degrees read from sensor.
*/
__STATIC_INLINE void data_handler(uint8_t temp)
{
//NRF_LOG_INFO("Temperature: %d Celsius degrees.", temp);
iDebug("TWI device Read Value 0x%d.", temp);
}
/**
* @brief TWI events handler.
*/
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
//iDebug("TWI handler 0x%d.", p_event->type);
switch (p_event->type)
{
case NRF_DRV_TWI_EVT_DONE:
if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
{
data_handler(m_sample);
}
m_xfer_done = true;
break;
default:
break;
}
}
/**
* @brief TWI initialization.
*/
void twi_init (void)
{
ret_code_t err_code;
const nrf_drv_twi_config_t twi_config = {
.scl = SCL_PIN,
.sda = SDA_PIN,
.frequency = NRF_DRV_TWI_FREQ_100K,
.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
.clear_bus_init = false
};
err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_twi_enable(&m_twi);
}
/**
* @brief Function for reading data from temperature sensor.
*/
void ScanTWI(){
twi_init();
}
void DataFilter(uint8_t *data, uint16_t len)
{
SendMode=0;
GetModbusValue = 0;
//iDebug("DataFilter \n");
if(!strncmp((char *)data, "getcurrent", 10))
{
PeriodicRead = 0;
GetCurrentValue = 1;
}
else if(!strncmp((char *)data, "getperiodic", 11))
{
PeriodicRead = 1;
}
else if(!strncmp((char *)data, "stop", 4))
{
PeriodicRead = 0;
}
else if(data[0] == 0x01) //Slave ID
{
//iDebug("DataFilter 1 \n");
if(data[1] == 0x03) //Read Holding Reg.
{
//Start Address data[2] & data[3]
ModStartAddr = data[3] |(data[2] << 8);
//iDebug("ModStartAddr : %d, data[2] : %d, data[3] : %d \n", ModStartAddr, data[2], data[3]);
//Length data[4] & data[5]
ModDataLen = data[5] | (data[4] << 8);
//iDebug("ModDataLen : %d, data[4] : %d, data[5] : %d \n",ModDataLen,data[4], data[5]);
//CRC data[6] & data[7]
PeriodicRead = 0;
GetCurrentValue = 0;
GetModbusValue = 1;
SendMode=1;
}
else if(data[1] == 0x06) //Write Holding Reg.
{
//BLEdeInit();
//bluetooth_sleep();
//nrf_delay_ms(500);
iDebug("Write Start :");
img[0] = data[2] ;
img[1] = data[3] ;
img[2] = data[4] ;
img[3] = data[5] ;
img1[0] = data[6] ;
img1[1] = data[7] ;
img1[2] = data[8] ;
img1[3] = data[9] ;
for (int i = 0; i < 4; i++){
iDebug(" %d, ",img[i]);
}
for (int i = 0; i < 4; i++){
iDebug(" %d, ",img1[i]);
}
CalibValue4mA = data[3] |(data[2] << 8);
CalibValue20mA = data[5] |(data[4] << 8);
ProcessValue4mA = data[7] |(data[6] << 8);
ProcessValue20mA = data[9] |(data[8] << 8);
iDebug("CalibValue4mA %d, ",CalibValue4mA);
iDebug("CalibValue20mA %d, ",CalibValue20mA);
iDebug("ProcessValue4mA %d, ",ProcessValue4mA);
iDebug("ProcessValue20mA %d, ",ProcessValue20mA);
iDebug("\r\nfs erase started.");
erase_from_flash();
nrf_delay_ms(500);
write_to_flash(1);
nrf_delay_ms(500);
iDebug("Write 1 ");
write_to_flash(2);
nrf_delay_ms(500);
iDebug("Write Finished ");
read_from_flash(1);
nrf_delay_ms(500);
read_from_flash(2);
}
}
}
uint8_t Bit_test(uint32_t var, uint8_t var_bit)
{
if((var & ((uint32_t)1 << var_bit)))
return 1;
return 0;
}
uint16_t CalcCRC(uint8_t *Logbuffer, uint8_t MsgLen)
{
uint16_t CRC, i;
uint8_t j, *Ptr8, Val, CRCLSB;
i = 0;
CRC = 0xffff;
Ptr8 = Logbuffer; // Preload with ffff
do{
Val = *Ptr8;
CRC = CRC ^ Val;
Ptr8++;
j = 0;
do{
if(Bit_test(CRC, 0))CRCLSB = 1;
else CRCLSB = 0;
CRC >>= 1; // Shift one bit to the right
if(CRCLSB) CRC = CRC ^ 0xa001;
}while(++j < 8);
i++;
}while(--MsgLen); // For all message bytes
return CRC;
}
void SendValue(TransportMode_t Mode)
{
dist_meas_result_t dist_meas_result;
ReadDetection(&dist_meas_result);
if(Mode == Ble)
{
BLEPrintf("Distance = %u mm \n",(unsigned int)(dist_meas_result.distance * 1000));
BLEPrintf("Signal Strength = %u\n",dist_meas_result.signal_strength);
BLEPrintf("Data Saturated = %d \n",dist_meas_result.data_saturated);
}
else if(Mode == Serial)
{
if(SendMode==0){
char temp[128] = {0};
sprintf(temp, "Distance = %u mm \nSignal Strength = %lu\nData Saturated = %ld \n",(unsigned int)(dist_meas_result.distance * 1000), dist_meas_result.signal_strength, dist_meas_result.data_saturated);
SendData(temp, strlen(temp));
}
else if(SendMode==1){
uint8_t idx=0,SendData[64] = {0xff}, DataCRC[2] = {0xff};
uint16_t DataDistance = 0,DataSaturated=0,DataSignalStrength=0;
uint16_t CRCVal=0;
//iDebug("Modbuas idx 0 : %d\n",idx);
SendData[idx++] = 0x01; // Salve Address
//iDebug("Modbuas idx 1 : %d\n",idx);
SendData[idx++] = 0x03; // Function code - Read Holding Reg
//iDebug("Modbuas idx 2 : %d\n",idx);
SendData[idx++] = ModDataLen * 2; // Length
//iDebug("Modbuas idx 3 : %d\n",idx);
DataDistance = dist_meas_result.distance * 1000;
DataSaturated = dist_meas_result.data_saturated;
DataSignalStrength = dist_meas_result.signal_strength;
if(ModDataLen ==1){
SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
SendData[idx++] = DataDistance & 0xFF; // Data
//iDebug("Modbuas idx 4 : %d\n",idx);
}
if(ModDataLen ==2){
SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
SendData[idx++] = DataDistance & 0xFF; // Data
SendData[idx++] = (DataSignalStrength >> 8) & 0xFF; //Signal Hi
SendData[idx++] = (DataSignalStrength) & 0xFF;//SignalStrength Lo
}
if(ModDataLen ==3){
SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
SendData[idx++] = DataDistance & 0xFF; // Data
SendData[idx++] = (DataSignalStrength >> 8) & 0xFF; //Signal Hi
SendData[idx++] = (DataSignalStrength) & 0xFF;//SignalStrength Lo
SendData[idx++] = (DataSaturated >> 8) & 0xFF;//Saturated Hi
SendData[idx++] = (DataSaturated) & 0xFF; ; // SaturatedLo
}
else{
SendData[idx++] = (DataDistance >> 8) & 0xFF; // Data
SendData[idx++] = DataDistance & 0xFF; // Data
SendData[idx++] = (DataSignalStrength >> 8) & 0xFF; //Signal Hi
SendData[idx++] = (DataSignalStrength) & 0xFF;//SignalStrength Lo
SendData[idx++] = (DataSaturated >> 8) & 0xFF;//Saturated Hi
SendData[idx++] = (DataSaturated) & 0xFF; ; // SaturatedLo
SendData[idx++] = (DataSaturated >> 8) & 0xFF;//Saturated Hi
SendData[idx++] = (DataSaturated) & 0xFF; ; // SaturatedLo
}
//iDebug("Modbuas idx : %d\n",idx);
CRCVal = CalcCRC(&SendData[0],idx );
DataCRC[0] = (CRCVal >> 8) & 0xFF;
DataCRC[1] = (CRCVal) & 0xFF;
SendData[idx++] = DataCRC[1];// CRC Hi
SendData[idx++] = DataCRC[0]; // CRC Lo
//iDebug("Modbuas idx - 1 : %d\n",idx);
SendModData(SendData,idx);
}
}
}
void StartRadarApp()
{
InitRadar();
iDebug("Application started.");
// Initialize
nrf_fstorage_api_t * p_fs_api;
p_fs_api = &nrf_fstorage_sd;
iDebug("fs Init started.");
nrf_fstorage_init(&my_instance,/*fstorage instance,previously defined. */
p_fs_api, /* Name of the backend. */
NULL /* Optional parameter, backend-dependant. */
);
nrf_delay_ms(500);
iDebug(" BLE started. ");
BLEInit();
iDebug(" fs read started. ");
uint32_t pgnum = NRF_FICR->CODESIZE-1;
uint32_t pgsize = NRF_FICR->CODEPAGESIZE;
iDebug(" fs pgnum %ul",pgnum);
iDebug(" fs pgsize %ul ",pgsize);
read_from_flash(1);
nrf_delay_ms(500);
read_from_flash(2);
nrf_delay_ms(100);
for (;;)
{
uint8_t buff[128] = {0};
uint16_t bufflen = 0;
if(BleReceiveData(buff, &bufflen))
{
DataFilter(buff, bufflen);
memset(buff, 0 ,sizeof(buff));
bufflen = 0;
IncomingTransportMode = Ble;
}
if(RecvData(buff, &bufflen))
{
//iDebug("Application started 1 ");
//nrf_delay_ms(500);
DataFilter(buff, bufflen);
memset(buff, 0 ,sizeof(buff));
bufflen = 0;
IncomingTransportMode = Serial;
}
if(GetCurrentValue)
{
SendValue(IncomingTransportMode);
GetCurrentValue = 0;
}
if(GetModbusValue){
IncomingTransportMode = Serial;
SendValue(IncomingTransportMode);
GetModbusValue=0;
}
if(PeriodicRead)
{
SendValue(IncomingTransportMode);
nrf_delay_ms(1000);
}
//Function for running power management. Should run in the main loop.
nrf_pwr_mgmt_run();
}
}
==============================================
#include "Infa.h"
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define DEVICE_NAME "InfaRadar" /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */
BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
{
{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};
bool IsDataAvail;
uint8_t DataBuff[256] = {0};
uint16_t Datalen = 0;
/**@brief Function for assert macro callback.
*
* @details This function will be called in case of an assert in the SoftDevice.
*
* @warning This handler is an example only and does not fit a final product. You need to analyse
* how your product is supposed to react in case of Assert.
* @warning On assert from the SoftDevice, the system can only recover on reset.
*
* @param[in] line_num Line number of the failing ASSERT call.
* @param[in] p_file_name File name of the failing ASSERT call.
*/
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
app_error_handler(DEAD_BEEF, line_num, p_file_name);
}
/**@brief Function for initializing the timer module.
*/
static void timers_init(void)
{
ret_code_t err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for the GAP initialization.
*
* @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
* the device. It also sets the permissions and appearance.
*/
static void gap_params_init(void)
{
uint32_t err_code;
ble_gap_conn_params_t gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err_code = sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *) DEVICE_NAME,
strlen(DEVICE_NAME));
APP_ERROR_CHECK(err_code);
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
gap_conn_params.slave_latency = SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling Queued Write Module errors.
*
* @details A pointer to this function will be passed to each service which may need to inform the
* application about an error.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void nrf_qwr_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
/**@brief Function for handling the data from the Nordic UART Service.
*
* @details This function will process the data received from the Nordic UART BLE Service and send
* it to the UART module.
*
* @param[in] p_evt Nordic UART Service event.
*/
/**@snippet [Handling the data received over BLE] */
static void nus_data_handler(ble_nus_evt_t * p_evt)
{
if (p_evt->type == BLE_NUS_EVT_RX_DATA)
{
memcpy(DataBuff, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
Datalen = p_evt->params.rx_data.length;
//PrintData((char *)p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
}
}
/**@snippet [Handling the data received over BLE] */
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
uint32_t err_code;
ble_nus_init_t nus_init;
nrf_ble_qwr_init_t qwr_init = {0};
// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);
// Initialize NUS.
memset(&nus_init, 0, sizeof(nus_init));
nus_init.data_handler = nus_data_handler;
err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling an event from the Connection Parameters Module.
*
* @details This function will be called for all events in the Connection Parameters Module
* which are passed to the application.
*
* @note All this function does is to disconnect. This could have been done by simply setting
* the disconnect_on_fail config parameter, but instead we use the event handler
* mechanism to demonstrate its use.
*
* @param[in] p_evt Event received from the Connection Parameters Module.
*/
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
uint32_t err_code;
if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
{
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
APP_ERROR_CHECK(err_code);
}
}
/**@brief Function for handling errors from the Connection Parameters module.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void conn_params_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
/**@brief Function for initializing the Connection Parameters module.
*/
static void conn_params_init(void)
{
uint32_t err_code;
ble_conn_params_init_t cp_init;
memset(&cp_init, 0, sizeof(cp_init));
cp_init.p_conn_params = NULL;
cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
cp_init.disconnect_on_fail = false;
cp_init.evt_handler = on_conn_params_evt;
cp_init.error_handler = conn_params_error_handler;
err_code = ble_conn_params_init(&cp_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for putting the chip into sleep mode.
*
* @note This function will not return.
*/
static void sleep_mode_enter(void)
{
uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
APP_ERROR_CHECK(err_code);
// Prepare wakeup buttons.
err_code = bsp_btn_ble_sleep_mode_prepare();
APP_ERROR_CHECK(err_code);
// Go to system-off mode (this function will not return; wakeup will cause a reset).
err_code = sd_power_system_off();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling advertising events.
*
* @details This function will be called for advertising events which are passed to the application.
*
* @param[in] ble_adv_evt Advertising event.
*/
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
uint32_t err_code;
switch (ble_adv_evt)
{
case BLE_ADV_EVT_FAST:
err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
APP_ERROR_CHECK(err_code);
break;
case BLE_ADV_EVT_IDLE:
sleep_mode_enter();
break;
default:
break;
}
}
/**@brief Function for handling BLE events.
*
* @param[in] p_ble_evt Bluetooth stack event.
* @param[in] p_context Unused.
*/
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
uint32_t err_code;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
NRF_LOG_INFO("Connected");
err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
APP_ERROR_CHECK(err_code);
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
APP_ERROR_CHECK(err_code);
break;
case BLE_GAP_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected");
// LED indication will be changed when advertising starts.
m_conn_handle = BLE_CONN_HANDLE_INVALID;
break;
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
NRF_LOG_DEBUG("PHY update request.");
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
} break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// Pairing not supported
err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
// No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTC_EVT_TIMEOUT:
// Disconnect on GATT Client timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
default:
// No implementation needed.
break;
}
}
/**@brief Function for the SoftDevice initialization.
*
* @details This function initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
ret_code_t err_code;
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// Register a handler for BLE events.
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
/*
#ifdef SOFTDEVICE_PRESENT
static void ble_stack_init(void)
{
ret_code_t err_code;
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// Register a handler for BLE events.
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
#else
static void clock_init(void){
// Initialize the clock.
ret_code rc = nrf_drv_clock_init();
APP_ERROR_CHECK(rc);
nrf_drv_clock_lfclk_request(NULL);
while(!nrf_clock_lf_is_running()) {;}
}
#endif*/
/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
{
m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
}
NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
p_gatt->att_mtu_desired_central,
p_gatt->att_mtu_desired_periph);
}
/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
ret_code_t err_code;
err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling events from the BSP module.
*
* @param[in] event Event generated by button press.
*/
void bsp_event_handler(bsp_event_t event)
{
uint32_t err_code;
switch (event)
{
case BSP_EVENT_SLEEP:
sleep_mode_enter();
break;
case BSP_EVENT_DISCONNECT:
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
if (err_code != NRF_ERROR_INVALID_STATE)
{
APP_ERROR_CHECK(err_code);
}
break;
case BSP_EVENT_WHITELIST_OFF:
if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
{
err_code = ble_advertising_restart_without_whitelist(&m_advertising);
if (err_code != NRF_ERROR_INVALID_STATE)
{
APP_ERROR_CHECK(err_code);
}
}
break;
default:
break;
}
}
/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = false;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.srdata.uuids_complete.p_uuids = m_adv_uuids;
init.config.ble_adv_fast_enabled = true;
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;
init.evt_handler = on_adv_evt;
err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
/**@brief Function for initializing buttons and leds.
*
* @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up.
*/
static void buttons_leds_init(bool * p_erase_bonds)
{
bsp_event_t startup_event;
uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
APP_ERROR_CHECK(err_code);
err_code = bsp_btn_ble_init(NULL, &startup_event);
APP_ERROR_CHECK(err_code);
*p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
}
/**@brief Function for starting advertising.
*/
static uint32_t advertising_start(void)
{
uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
return err_code;
}
uint32_t bluetooth_sleep(void)
{
uint32_t err_code;
iDebug("sd_ble_gap_disconnect 1 \n");
// If connected, disconnect
if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
{
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
if (err_code != NRF_SUCCESS) return err_code;
}
iDebug("sd_ble_gap_adv_stop 1 \n");
// Stop advertising
err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
if (err_code != NRF_SUCCESS) return err_code;
iDebug("TASKS_DISABLE 1 \n");
// Disable the radio tasks as scytulip suggested
// devzone.nordicsemi.com/.../
//NRF_RADIO->TASKS_DISABLE =1;
//NRF_RADIO->POWER=0;
iDebug("NRF_SUCCESS 1 \n");
return NRF_SUCCESS;
}
uint32_t bluetooth_wake(void)
{
uint32_t err_code;
err_code = advertising_start();
if (err_code != NRF_SUCCESS) return err_code;
return NRF_SUCCESS;
}
void BLEInit()
{
bool erase_bonds;
timers_init();
buttons_leds_init(&erase_bonds);
////power_management_init();
ble_stack_init();
/*#ifdef SOFTDEVICE_PRESENT
ble_stack_init();
#else
clock_init();
#endif */
iDebug("gap_params_init \n");
gap_params_init();
gatt_init();
services_init();
advertising_init();
conn_params_init();
//Start execution.
advertising_start();
}
uint16_t BLESend(uint8_t *data, uint16_t length)
{
if(m_conn_handle == BLE_CONN_HANDLE_INVALID)
{
return 0;
}
ble_nus_data_send(&m_nus, data, &length, m_conn_handle);
nrf_delay_ms(50);
return length;
}
void BLEPrintf(const char * format, ... )
{
char buffer[256];
va_list args;
va_start(args, format);
vsnprintf(buffer, 256, format, args);
BLESend((uint8_t *)buffer, strlen(buffer));
va_end(args);
}
bool BleReceiveData(uint8_t *data, uint16_t *length)
{
if(Datalen == 0)
{
return 0;
}
memcpy(data, DataBuff, Datalen);
*length = Datalen;
memset(DataBuff, '0', Datalen);
Datalen = 0;
return 1;
}
Hello,
I am debugging using UART.
Please upload your full project as a .zip file here.
Here is how you upload attachments:
