This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to implement prepare write request on the master device side

Hi engineer,

I have developed a dongle that uses 52840 and is used as the master device. Now the data sent by the dongle to the slave device needs to use prepare write request. 

//code segment

static uint8_t m_lts_buf[MEM_LENGTH];
static ble_user_mem_block_t m_lts_mem = {
	.p_mem = m_lts_buf,
	.len = MEM_LENGTH
};
static uint16_t prepare_handle;
static uint8_t prepare_buf[MEM_LENGTH];
static uint16_t prepare_offset;
static uint16_t prepare_length;
#define PREPARE_LEN  (BLE_NUS_MAX_DATA_LEN - 2)


uint32_t prepare_write(uint8_t* mac, uint8_t* pBuf, uint16_t len)
{
	
	memset(prepare_buf, 0, MEM_LENGTH);
	prepare_offset = 0;
	if(find_handle_by_mac(mac, &prepare_handle) == NRF_ERROR_NOT_FOUND){
		return NRF_ERROR_NOT_FOUND;
	}

	prepare_length = len > MEM_LENGTH ? MEM_LENGTH : len;

	memcpy(prepare_buf, pBuf, prepare_length);


	uint32_t retval = client_prepare_write_request(prepare_handle, prepare_buf, PREPARE_LEN, prepare_offset);
	prepare_offset += PREPARE_LEN;

	return retval;
	
	
}

void on_ble_evt(const ble_evt_t * const p_ble_evt)
{

    case BLE_EVT_USER_MEM_REQUEST:			
			NRF_LOG_DEBUG("BLE_EVT_USER_MEM_REQUEST");
			err_code = sd_ble_user_mem_reply(p_gap_evt->conn_handle, &m_lts_mem);
			//simple_uart_putstring("User mem request \r\n");
		break;
		case BLE_EVT_USER_MEM_RELEASE:
			if ((p_ble_evt->evt.common_evt.params.user_mem_release.mem_block.p_mem == m_lts_mem.p_mem)
				&&(p_ble_evt->evt.common_evt.params.user_mem_release.mem_block.len == m_lts_mem.len)){
				NRF_LOG_DEBUG("mem release nothing");
			}
			NRF_LOG_DEBUG("BLE_EVT_USER_MEM_RELEASE");	
		break;
		case BLE_GATTC_EVT_WRITE_RSP:{
			NRF_LOG_DEBUG("BLE_GATTC_EVT_WRITE_RSP");

			uint8_t temp_data[PREPARE_LEN];						
			
			if(p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL)
			{
				client_prepare_write_exec(p_gap_evt->conn_handle);

				
			}
			else
			{
				
				if(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op == BLE_GATT_OP_PREP_WRITE_REQ)
				{
					if(prepare_offset == prepare_length){
					    //prepare write Execute
						client_prepare_write_exec(p_gap_evt->conn_handle);
						break;
					}
					
					if(prepare_offset + PREPARE_LEN > prepare_length){
						//prepare write request. Last packet of data
						client_prepare_write_request(p_gap_evt->conn_handle, 
							prepare_buf + prepare_offset, prepare_length - prepare_offset, prepare_offset);
						prepare_offset = prepare_length;
					}else{
						//prepare write request
						client_prepare_write_request(p_gap_evt->conn_handle, 
							prepare_buf + prepare_offset, PREPARE_LEN, prepare_offset);
						prepare_offset += PREPARE_LEN;
					}
				}else if(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op == 
					BLE_GATT_OP_EXEC_WRITE_REQ){
					
					NRF_LOG_DEBUG("BLE_GATT_OP_EXEC_WRITE_REQ");
					
				}
			}
			
		}break;

}


uint32_t client_prepare_write_exec(uint16_t handle)
{
	uint32_t   index;
	client_t * p_client;
	uint32_t retval = NRF_ERROR_NO_MEM;
    index = client_find(handle);
    if(index == MAX_CLIENTS) return NRF_ERROR_NOT_FOUND;
    p_client = &m_client[index];

	ble_gattc_write_params_t write_params = {
        .write_op = BLE_GATT_OP_EXEC_WRITE_REQ,
        .flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
        .handle   = 0,
        .offset   = 0,
        .len      = 0,
        .p_value  = NULL,
    };
    
	retval = NRF_ERROR_NO_MEM;
    
    write_params.handle = p_client->srv_db.services[p_client->srv_db.curr_srv_ind].charateristics[p_client->char_index].characteristic.handle_value;
    retval = sd_ble_gattc_write(p_client->srv_db.conn_handle, &write_params);
    NRF_LOG_DEBUG("gattc write retval %d", retval);
	
	return retval;


}

uint32_t client_prepare_write_request(uint16_t handle, uint8_t * p_string, uint16_t length, uint16_t offset)
{
	uint32_t   index;
	client_t * p_client;
	uint32_t retval = NRF_ERROR_NO_MEM;
    index = client_find(handle);
    if(index == MAX_CLIENTS) return NRF_ERROR_NOT_FOUND;
    p_client = &m_client[index];

	ble_gattc_write_params_t write_params = {
        .write_op = last ? BLE_GATT_OP_EXEC_WRITE_REQ : BLE_GATT_OP_PREP_WRITE_REQ,
        .flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
        .handle   = 0,
        .offset   = offset,
        .len      = length,
        .p_value  = p_string,
    };
    NRF_LOG_DEBUG("p_string %s, length %d, offset %d", p_string, length, offset);
	retval = NRF_ERROR_NO_MEM;
    
    write_params.handle = p_client->srv_db.services[p_client->srv_db.curr_srv_ind].charateristics[p_client->char_index].characteristic.handle_value;
    retval = sd_ble_gattc_write(p_client->srv_db.conn_handle, &write_params);
    NRF_LOG_DEBUG("gattc write retval %d", retval);
	
	return retval;

}

This is my code, I call prepare_write() first, then send(use prepare write requese) the remaining data in the BLE_GATTC_EVT_WRITE_RSP event .

When the data is sent, start to execute prepare write Execute.

Can successfully send data to the slave device.

However, when I send the next command using BLE_GATT_OP_WRITE_CMD, it will prompt an error: SD Read/Write API returns error

The error code is 7, error code 7 meansInvalid Parameter

please help me.

Related