16 posts / 0 new
Last post
sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
documentation

Hello,

I could not find any document talking about functionality of the peripherals of 14580 (or others) and how to set them up for different options.

I2C, SPI, A/D, PWM,....etc.

Can anybody point me to such document please?

Device: 
MT_dialog
Offline
Last seen: 1 year 7 months ago
Staff
Joined: 2015-06-08 11:34
Hi sjabir2004,

Hi sjabir2004,

Please have a look at the documents UM-B-050 at the peripheral examples applications section (7) and also you can have a look to the doc UM-B-051 in the peripheral drivers section (10) for the drivers of the peripherals.

Thanks MT_dialog

sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
Hello,

Hello,

I have already seen these documents.
There is no description of the hardware structure of the peripherals and how these can be setup . The examples cannot cover all possible combinations and functionalities.

Please confirm that this document is missing.

MT_dialog
Offline
Last seen: 1 year 7 months ago
Staff
Joined: 2015-06-08 11:34
Hi sjabir2004,

Hi sjabir2004,

There are no other documents concerning the da peripherals and the developed APIs, for more info about any additional functionalities can be found in the da's datasheet. Also you might want to have a look at the documents UM-B-005 and UM-B-004 to check if those documents cover any additional functionalities.

Thanks MT_dialog

sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
Example : I want to command a

Example : I want to command a sensor with I2C. I need to send command write then eventual read . Read can be of max N bytes.

I dont know how to set the bits and bytes in the I2C registers to send and receive because it is not written anywhere !.

What functions of the i2c_eeprom example are usable in this case ?

Thank you !

MHv_Dialog
Offline
Last seen: 1 year 2 months ago
Staff
Joined: 2013-12-06 15:10
Hi,

Hi,

I don't believe that the I2C functions of the i2c_eeprom example is a great starting point for a sensor driver. I have been using the example below which better explains how to attack I2C:

/****************************************************************************************
* MACROS
****************************************************************************************/
// I2C helper macros
#define SEND_I2C_COMMAND(X)             SetWord16(I2C_DATA_CMD_REG, (X))
#define WAIT_WHILE_I2C_FIFO_IS_FULL()   while(!(GetWord16(I2C_STATUS_REG) & TFNF))
#define WAIT_UNTIL_I2C_FIFO_IS_EMPTY()  while(!(GetWord16(I2C_STATUS_REG) & TFE))
#define WAIT_UNTIL_NO_MASTER_ACTIVITY() while(GetWord16(I2C_STATUS_REG) & MST_ACTIVITY)
#define WAIT_FOR_RECEIVED_BYTE()        while(!GetWord16(I2C_RXFLR_REG))

/*---------------------------------------------------------------------------------------
| @brief      Initializes the I2C interface with the provide slave address
|
| @param[in]  slave_address, The I2C slave address to communicate with
|
| @return     void
---------------------------------------------------------------------------------------*/
void i2c_init(uint8_t slave_address)
{
  // Initialize the I2C with the address provided as argument
  // TODO: Support 10bit addressing
  SetBits16(CLK_PER_REG, I2C_ENABLE, 1);                                       // Enable  clock for I2C 
  SetWord16(I2C_ENABLE_REG, 0x0);                                              // Disable the I2C controller  
  SetWord16(I2C_CON_REG, I2C_MASTER_MODE | I2C_SLAVE_DISABLE |I2C_RESTART_EN); // Slave is disabled
  SetBits16(I2C_CON_REG, I2C_SPEED, 1);                                        // Set speed. Standard speed = 1, fast = 2
  SetBits16(I2C_CON_REG, I2C_10BITADDR_MASTER, 0);                             // Set addressing mode. 7bit = 0, 10bit= 1
  SetWord16(I2C_TAR_REG, slave_address & 0xFF);                                // Set Slave device address
  SetWord16(I2C_ENABLE_REG, 0x1);                                              // Enable the I2C controller
  while(GetWord16(I2C_STATUS_REG) & 0x20);                                     // Wait for I2C master FSM to be IDLE
}  
//

/*---------------------------------------------------------------------------------------
| @brief      Scans the I2C bus for slave devices
|
| @param[in]  extended, if true: Response will include potential I2C slave device IDs
| @param[in]  remote, originator of the scan command
|
| @return     void
---------------------------------------------------------------------------------------*/
void i2c_scan(bool extended,bool remote)
{
  char temp_str[255] = {0};
  char response_str[255] = {0};
  uint8_t response_idx=0;
  
  // Run through all I2C addresses (7bit addressing only!)  
  for(uint8_t i = 0x01; i < 0x7F; i++)
  {
    // Set next slave address
    i2c_init(i);
    
    SEND_I2C_COMMAND(0x00 & 0x3FF);                 // Transmit Address on bus
    WAIT_WHILE_I2C_FIFO_IS_FULL();                  // Wait if I2C Tx FIFO is full
    SEND_I2C_COMMAND(0x0100 & 0x3FF);               // Send read register 0x00
    WAIT_UNTIL_I2C_FIFO_IS_EMPTY();                 // Wait until Tx FIFO is empty
    WAIT_UNTIL_NO_MASTER_ACTIVITY();                // Make sure Master has finished
    
    // Did we receive any data?
    if(GetWord16(I2C_RXFLR_REG) != 0)
    {
      // Read the received data (device_id)
      uint8_t device_id =0xFF & GetWord16(I2C_DATA_CMD_REG);
      // If this is an extended scan then report the device ID as well as the address
      if(extended)
        // Extended scan. Report address and register 0x00 (device_id)
        sprintf(temp_str, "0x%02X=>0x%02X,",i,device_id);
      else 
        // Normal scan => report address
        sprintf(temp_str, "0x%02X,",i);
      memcpy(&response_str[response_idx],temp_str,strlen(temp_str));
      // Warning: will fail if more than 50 I2C devices available on bus  
      response_idx += strlen(temp_str);
    }
    
  }
  // Append Carriage-return, Linefeed and 'OK' to response
  sprintf(temp_str,"\n\rOK");
  memcpy(&response_str[response_idx-1],temp_str,strlen(temp_str));
  // Display response (remote or locally)
  respond(response_str,strlen(response_str),remote);

  // Disable I2C
  SetWord16(I2C_ENABLE_REG, 0x0);         // Disable the I2C controller  
  SetBits16(CLK_PER_REG, I2C_ENABLE, 0);  // Disable clock for I2C
  
}
//

/*---------------------------------------------------------------------------------------
| @brief Send I2C slave memory address
|
| @param[in] address of the I2C slave memory
---------------------------------------------------------------------------------------*/
void i2c_send_address(uint8_t address_to_send)
{
    
    SEND_I2C_COMMAND(address_to_send & 0xFF);                   // Set address LSB, write access    
}
//

/*---------------------------------------------------------------------------------------
| @brief      Reads single byte from I2C slave.
|
| @param[in]  address, Memory address to read the byte from.
|
| @return     Read byte.
---------------------------------------------------------------------------------------*/
int8_t i2c_read_byte(uint8_t address)
{
    i2c_send_address(address & 0x3FF);  
    WAIT_WHILE_I2C_FIFO_IS_FULL();                  // Wait if Tx FIFO is full
    SEND_I2C_COMMAND(0x0100 & 0x3FF);               // Set R/W bit to 1 (read access)
    WAIT_UNTIL_I2C_FIFO_IS_EMPTY();                 // Wait until I2C Tx FIFO empty
    WAIT_UNTIL_NO_MASTER_ACTIVITY();                // Make sure master has finished  
    return (0xFF & GetWord16(I2C_DATA_CMD_REG));    // Get received byte
}
//

/*---------------------------------------------------------------------------------------
| @brief      Writes single byte to I2C slave.
|
| @param[in]  address, Memory address to write the byte to.
| @param[in]  wr_data, Data to write.
|
| @return     void.
---------------------------------------------------------------------------------------*/
void i2c_write_byte(uint16_t address, uint8_t wr_data)
{
  i2c_send_address(address);       
  WAIT_WHILE_I2C_FIFO_IS_FULL();                  // Wait if I2C Tx FIFO is full
  SEND_I2C_COMMAND(wr_data & 0xFF);               // Send write data
  WAIT_UNTIL_I2C_FIFO_IS_EMPTY();                 // Wait until Tx FIFO is empty    
  WAIT_UNTIL_NO_MASTER_ACTIVITY();                // wait until no master activity 
}
//

/*---------------------------------------------------------------------------------------
| @brief      Reads data from an I2C slave
|
| @param[in]  hw_address, HW address of I2C slave device
| @param[in]  reg_address, Register address to be read
| @param[in]  num_bytes, Number of bytes to read
| @param[in]  remote, originator of the read command
|
| @return     void
---------------------------------------------------------------------------------------*/
void i2c_read(uint16_t hw_address,uint16_t reg_address, uint8_t num_bytes, bool remote)
{
    char temp_str[255] = {0};
    i2c_init(hw_address);
    for(uint8_t i=0;i<num_bytes;i++)
    {
      uint8_t data = i2c_read_byte(reg_address+i);
      char str[10];
        if(i==0)
            sprintf(str,"0x%02X",data);
        else
            sprintf(str,",0x%02X",data);
        sprintf(temp_str,"%s%s",temp_str,str);
    }
    sprintf(temp_str,"%s\n\rOK",temp_str);
    respond(temp_str,strlen(temp_str),remote);
}
//

/*---------------------------------------------------------------------------------------
| @brief      Writes data to a register address of an I2C slave
|
| @param[in]  hw_address, HW address of I2C slave device
| @param[in]  reg_address, Register address to write to
| @param[in]  data, Data to write
| @param[in]  remote, originator of the read command
|
| @return     void
---------------------------------------------------------------------------------------*/
void i2c_write(uint16_t hw_address,uint16_t reg_address, uint16_t wr_data, bool remote)
{
    i2c_init(hw_address);
    i2c_write_byte(reg_address,wr_data);
    respond_ok(remote);
}
//

I hope this helps.

sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
Ok this seems what I was

Ok this seems what I was looking for. I will give it a try.

I don't know why don't you add this in the documentation and libraries of the SDK !!, many people in this forum will be happy. There are so many I2C devices on the market, each with own structure and protocol.

thank you!

sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
Hello , where do I find these

Hello , where do I find these functions
sprintf(temp_str,"%s\n\rOK",temp_str);
respond(temp_str,strlen(temp_str),remote);

sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
Sorry I mean respond() and

Sorry I mean respond() and respond_ok()

MHv_Dialog
Offline
Last seen: 1 year 2 months ago
Staff
Joined: 2013-12-06 15:10
Hi,

Hi,

sprintf is from the stdlib library (just #include "stdlib.h") - really useful when you want to dump data to a user or during debugging.

The two respond functions are just a set of functions that i have implemented to dump the data to a serial port. You can use UART2 and arch_printf to do this in your code.

I agree that this should be added to the documentation - useful material for a quick tutorial.  

sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
Hello, ok , this is clear .

Hello, ok , this is clear .
In your code above ,
......................
void i2c_write_byte(uint16_t address, uint8_t wr_data)
{
i2c_send_address(address);
WAIT_WHILE_I2C_FIFO_IS_FULL(); // Wait if I2C Tx FIFO is full
SEND_I2C_COMMAND(wr_data & 0xFF); // Send write data
WAIT_UNTIL_I2C_FIFO_IS_EMPTY(); // Wait until Tx FIFO is empty
WAIT_UNTIL_NO_MASTER_ACTIVITY(); // wait until no master activity
}
The TAR register contains the address of the slave and the DATA_CMD register contains the data to send . i2c_send_address(address) will write the address to the DATA_CMD register and then SEND_I2C_COMMAND(wr_data..) will do the same ! .

Is this a mistake or I am missing something?
SHould all go through the DATA_CMD_REG? i.e. address of target and data to send?
If yes , what is the scope of TAR_REG bits 0:7?

What is simply the mechanism to :
1-send one command to a slave?
Command could be read, write, reset , ..
2- Read N. bytes from a slave device?
All without interrupts , just to get it easy.
Thank you !

MT_dialog
Offline
Last seen: 1 year 7 months ago
Staff
Joined: 2015-06-08 11:34
Hi sjabir2004,

Hi sjabir2004,

The IC_TAR register contains the address of the slave device, in the i2c driver the device will first write the register address of the module, that it wants to read/write to the DATA_CMD, and then, place in the DATA_CMD register the data to be transmitted. The I2C_TAR is the address of the device itself the setting of your device address is set during the i2c initialization.

Thanks MT_dialog

sjabir2004@yahoo.com
Offline
Last seen: 6 years 8 months ago
Joined: 2015-09-18 22:13
Hello

Hello

The I2C_TAR contains the address of the i2c DEVICE to which the DA14580 would write to.
The DATA_CMD_REG contains the data to communicate to the DEVICE.

When I write to the DATA_CMD_REG any data , on the i2c bus you have first the I2C_TAR_REG followed by the I2C_DATA_REG content.

If I write the slave address to the DATA_CMD_REG , you will have the address TWO times on the bus !!

If there is single i2c DEVICE on the bus , one needs to load the TAR_REG once and then writes data to DATA_CMD_REG then I get address-->Data sent to the device,

This is what I see on the memory oscilloscope.

Am I missing something here ?

MT_dialog
Offline
Last seen: 1 year 7 months ago
Staff
Joined: 2015-06-08 11:34
Hi sjabir2004,

Hi sjabir2004,

What do you mean ? if you write the slave address of the device in the DATA_CMD_REG the module will send the I2C_TAR_REG (which is the address of the module) and then will send the data in the DATA_CMD_REG which is again the address of the module. You just need to initialize the I2C with the device that you want to communicate and and then each time you write something in the DATA_CMD_REG the address of the device will be on the bus followed along with the operation (read/write) followed by the data in the DATA_CMD_REG. After a stop or a restart condition when the i2c will start a new transaction the address of the device will be on the bus again. 

Thanks MT_dialog 

ajay98
Offline
Last seen: 9 months 3 weeks ago
Joined: 2018-07-10 12:12
Hello,

Hello,
i am using SDK 5.0.4 .in order to check security feature in DA14580 device i have to store bond data in EEPROM. while writing a byte in to EEPROM i am facing a problem of i2c_wait_until_eeprom_ready() function .it affects the debugging.
if ((GetWord16(SYS_STAT_REG) & DBG_IS_UP) == DBG_IS_UP)
__asm("BKPT #0\n");

my code was shown below like this,
************************************************************************************
/************************************************************
* Select memory medium for bond data storage:
*
* - SPI FLASH (#define USER_CFG_APP_BOND_DB_USE_SPI_FLASH)
* - I2C EEPROM (#define USER_CFG_APP_BOND_DB_USE_I2C_EEPROM)
* - cache only (define nothing)
*
* Select only one option.
************************************************************
*/
#undef USER_CFG_APP_BOND_DB_USE_SPI_FLASH
#define USER_CFG_APP_BOND_DB_USE_I2C_EEPROM

static inline void bond_db_load_ext(void)
{
#if defined (USER_CFG_APP_BOND_DB_USE_SPI_FLASH)
bond_db_load_flash();
#elif defined (USER_CFG_APP_BOND_DB_USE_I2C_EEPROM)
bond_db_load_eeprom();
#endif
}

#elif defined (USER_CFG_APP_BOND_DB_USE_I2C_EEPROM)

static void bond_db_load_eeprom(void)
{
uint32_t bytes_read;

i2c_eeprom_init(I2C_SLAVE_ADDRESS, I2C_SPEED_MODE, I2C_ADDRESS_MODE, I2C_ADDRESS_SIZE);

i2c_eeprom_read_data((uint8_t *)&bdb, APP_BOND_DB_DATA_OFFSET, sizeof(struct bond_db), &bytes_read);
ASSERT_ERROR(bytes_read == sizeof(struct bond_db));

i2c_eeprom_release();
}

i2c_error_code i2c_eeprom_read_data(uint8_t *rd_data_ptr, uint32_t address, uint32_t size, uint32_t *bytes_read)
{
uint32_t tmp_size;

if (size == 0)
{
*bytes_read = 0;
return I2C_NO_ERROR;
}

// Check for max bytes to be read from a (MAX_SIZE x 8) I2C EEPROM
if (size > I2C_EEPROM_SIZE - address)
{
tmp_size = I2C_EEPROM_SIZE - address;
*bytes_read = tmp_size;
}
else
{
tmp_size = size;
*bytes_read = size;
}

if (i2c_wait_until_eeprom_ready() != I2C_NO_ERROR)
{
return I2C_7B_ADDR_NOACK_ERROR;
}

// Read 32 bytes at a time
while (tmp_size >= 32)
{
read_data_single(&rd_data_ptr, address, 32);

address += 32; // Update base address for read
tmp_size -= 32; // Update tmp_size for bytes remaining to be read
}

if (tmp_size)
{
read_data_single(&rd_data_ptr, address, tmp_size);
}

return I2C_NO_ERROR;
}

i2c_error_code i2c_wait_until_eeprom_ready(void)
{
uint16_t tx_abrt_source;

// Check if ACK is received
for (uint32_t i = 0; i < I2C_MAX_RETRIES; i++)
{
SEND_I2C_COMMAND(0x08); // Make a dummy access
WAIT_UNTIL_I2C_FIFO_IS_EMPTY(); // Wait until Tx FIFO is empty
WAIT_UNTIL_NO_MASTER_ACTIVITY(); // Wait until no master activity
tx_abrt_source = GetWord16(I2C_TX_ABRT_SOURCE_REG); // Read the I2C_TX_ABRT_SOURCE_REG register
GetWord16(I2C_CLR_TX_ABRT_REG); // Clear I2C_TX_ABRT_SOURCE register
if ((tx_abrt_source & ABRT_7B_ADDR_NOACK) == 0)
{
return I2C_NO_ERROR;
}
}
return I2C_7B_ADDR_NOACK_ERROR;
}

note: if i loaded the bond data in sysram, it is working fine. i.e,
#undef USER_CFG_APP_BOND_DB_USE_SPI_FLASH
#undef USER_CFG_APP_BOND_DB_USE_I2C_EEPROM

please give a valuable suggesssition to avoid this problem.advance thanks.

PM_Dialog
Offline
Last seen: 6 months 3 weeks ago
Staff
Joined: 2018-02-08 11:03
Hi ajay98,

Hi ajay98,

The i2c_wait_until_eeprom_ready() is polling  the device via sending a 0x08 byte until the device responds with an ACK. Can you please run the code in debug mode and indicate in which point of i2c_wait_until_eeprom_ready() the code gets stuck? Also, which example of the SDK are you using? Is this a custom implementation? Would it be possible to replicate it in the ble_app_security example of the SDK?

I would also recommend you creating a new forum thread with your issue, as this one is very old.

Thanks, PM_Dialog