<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>TWIM Errata 109</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/105932/twim-errata-109</link><description>Hello Nordic, 
 I&amp;#39;ve been attempting to convert our system&amp;#39;s TWIM implementation from the blocking to the non-blocking mode. I have been able to communicate fine with the external device (an LIS2MDL Magnetometer) while in the blocking mode, however, when</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 22 Jul 2024 11:12:18 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/105932/twim-errata-109" /><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/495005?ContentTypeID=1</link><pubDate>Mon, 22 Jul 2024 11:12:18 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9c8131dc-8eca-4508-a58d-e32d703e95c6</guid><dc:creator>Robotics Gun</dc:creator><description>&lt;p&gt;For somebody who face the same issue, I leave the solution here.&amp;nbsp;&lt;span class="emoticon" data-url="https://devzone.nordicsemi.com/cfs-file/__key/system/emoji/1f601.svg" title="Grin"&gt;&amp;#x1f601;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Just use &amp;quot;TX&amp;quot; with two byte primary buffer&lt;/p&gt;
&lt;p&gt;primary_buffer[0] = register_address;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;primary_buffer[1] = value_to_write;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/494950?ContentTypeID=1</link><pubDate>Mon, 22 Jul 2024 01:26:05 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7c6a791e-ca6c-464a-886d-6fa164d6b371</guid><dc:creator>Robotics Gun</dc:creator><description>&lt;p&gt;I am facing the same issue.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Using nrf52832 and TX-RX works perfectly for 3D Magnetometer (MMC5603NJ)!&lt;/p&gt;
&lt;p&gt;&amp;gt;&amp;gt; getting product ID properly.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;However, TX-TX seems to have an issue that configuration never works.&lt;/p&gt;
&lt;p&gt;I checked all of the code and found no issue.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Unforunately, It&amp;#39;s very small PCB so I couldn&amp;#39;t put test-points on the board.&lt;/p&gt;
&lt;p&gt;So if it&amp;#39;s the issue I am facing and to work-around it, should I use TX twice instead of TX-TX?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/457926?ContentTypeID=1</link><pubDate>Tue, 28 Nov 2023 15:36:30 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b331003f-04f5-434c-9021-d5c81907514c</guid><dc:creator>jspear</dc:creator><description>&lt;p&gt;Vidar,&lt;/p&gt;
&lt;p&gt;Thanks again for all of your help! Looking at the LIS2MDL datasheet, I can see that it indeed is not expecting a repeated start, and so the repeated start on the TXTX descriptor would interfere with the expected behavior for the LIS2MDL. The implementation described a few messages ago will work, so thanks for helping get to the solution and the explanation!&lt;/p&gt;
&lt;p&gt;Joseph&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/457868?ContentTypeID=1</link><pubDate>Tue, 28 Nov 2023 13:28:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:063688bd-7244-4225-a8d7-7a47e3961c29</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello Joseph,&lt;/p&gt;
&lt;p&gt;Thanks for the update. I&amp;nbsp;think the problem is that the &amp;quot;TXTX&amp;quot; descriptor performs two transfers while the&amp;nbsp;&lt;span&gt;LIS2MDL slave expects the register to be set in a single transfer.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1701178097594v1.png" alt=" " /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Vidar&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/457656?ContentTypeID=1</link><pubDate>Mon, 27 Nov 2023 16:20:08 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:39371520-2b73-4564-b061-d890bfbbedfb</guid><dc:creator>jspear</dc:creator><description>&lt;p&gt;Hello again Vidar,&lt;/p&gt;
&lt;p&gt;Thanks for the advice! I attempted this fix&amp;nbsp;for the read and write functions, then played around with a couple of combinations of the fixes. It appears that the&amp;nbsp;NRFX_TWIM_XFER_TXRX descriptor in the read is working fine as long as the device has started (aka I modify the write to be just one&amp;nbsp;NRFX_TWIM_XFER_TX descriptor like that in the blocking mode). The&amp;nbsp;NRFX_TWIM_XFER_TXTX appears to be what is causing the issue&amp;nbsp;since when I use it,&amp;nbsp;the configurations on the magnetometer are not being updated. When I use the simpler&amp;nbsp;NRFX_TWIM_XFER_TX descriptor and just add the register address as the first byte in the tx_buff, then I can get it to work in non-blocking mode.&lt;/p&gt;
&lt;p&gt;This workaround can work, though I&amp;#39;d still like to know if I was somehow using the&amp;nbsp;NRFX_TWIM_XFER_TXTX descriptor wrong. Is there anything you can see that I may have missed with this?&lt;/p&gt;
&lt;p&gt;Joseph&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/457191?ContentTypeID=1</link><pubDate>Thu, 23 Nov 2023 14:13:33 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:018acee8-d6a7-48fa-820d-c76d8fbba644</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Joseph,&lt;/p&gt;
&lt;p&gt;Sorry if I&amp;#39;m overlooking something obvious, but I&amp;#39;m not sure I&amp;#39;m understanding why the transfer descriptor needs to be different for blocking and non-blocking transfers in twi_write(). Have you tried to see if it works if you use the same descriptor created with the NRFX_TWIM_XFER_DESC_TX() macro for non-blocking? A logic analyzer can be&amp;nbsp;very helpful for troubleshooting, if you have access to one. You could then compare the blocking transfers with the non-blocking ones to see if there are any differences.&lt;/p&gt;
&lt;p&gt;Vidar&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/456998?ContentTypeID=1</link><pubDate>Wed, 22 Nov 2023 15:46:47 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d06c9569-8dbd-4f98-bf3f-42923f4d50d5</guid><dc:creator>jspear</dc:creator><description>&lt;p&gt;Vidar,&lt;/p&gt;
&lt;p&gt;Thanks for your response, and thanks for letting me know that this&amp;nbsp;errata isn&amp;#39;t an issue for me.&lt;/p&gt;
&lt;p&gt;Following are the relevant code snippets of this process:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// 0 = Non-blocking mode enabled
// 1 = Blocking mode enabled
#define I2C_BLOCKING_MODE	1

static const nrfx_twim_t m_twim = NRFX_TWIM_INSTANCE(0);

static volatile uint8_t tx_buff[I2C_BUFF_SIZE] = {0};
static volatile uint8_t rx_buff[I2C_BUFF_SIZE] = {0};
static bool m_xfer_done = true;

ret_code_t	twim_init(void)
{
    ret_code_t status_code = NRF_SUCCESS;
    
	// Setup the twi configuration structure for initialization
	const nrfx_twim_config_t twi_config = {
		.scl                = I2C_SCL,  // Macro to the NRF Pin
		.sda                = I2C_SDA,  // Macro to the NRF Pin
		.frequency          = NRF_TWIM_FREQ_400K,
		.interrupt_priority = APP_IRQ_PRIORITY_HIGH,
		.hold_bus_uninit     = false
		};

	// Initialize the nrfx_twim module
#if(1 == I2C_BLOCKING_MODE)
	status_code = nrfx_twim_init(&amp;amp;m_twim, &amp;amp;twi_config, NULL, NULL);
#elif(0 == I2C_BLOCKING_MODE)
	status_code = nrfx_twim_init(&amp;amp;m_twim, &amp;amp;twi_config, I2C_Evt_Handler, NULL);
#endif	
	APP_ERROR_CHECK(status_code);

	// Enable the TWI module
	nrfx_twim_enable(&amp;amp;m_twim);

	// Initialization wait to allow module to settle
	vTaskDelay(pdMS_TO_TICKS(5));
	
	return status_code;
}


int32_t twi_write(	void * p_dev_addr, uint8_t reg_addr, 
							const uint8_t *reg_data, uint16_t cnt)
{ 
	ret_code_t status_code = NRF_SUCCESS;

	// Get the slave address
	static uint8_t loc_slave_addr 	= 0;
	static uint8_t loc_reg_addr 	= 0;
	static uint16_t loc_cnt 		= 0;

	// Don&amp;#39;t continue unless the previous transfer is complete
	while(false == m_xfer_done)
	{
		vTaskDelay(pdMS_TO_TICKS(1));
	}	/*	end while loop	*/

	// Update the local xfer data once the handler has finished
	loc_slave_addr 	= *(uint8_t*)p_dev_addr;
	loc_reg_addr 	= reg_addr;
	loc_cnt 		= cnt;

#if(1 == I2C_BLOCKING_MODE)
	// Store data in the tx buffer
	tx_buff[0] = reg_addr;
	memcpy(&amp;amp;tx_buff[1], reg_data, cnt);

	// Define a transmit transfer descriptor to be used in the next twi transfer
	nrfx_twim_xfer_desc_t xfer_desc =
		NRFX_TWIM_XFER_DESC_TX(loc_slave_addr, tx_buff, loc_cnt+1);

	// Transmit the register address and the data to be stored there. 
	status_code |= nrfx_twim_xfer(&amp;amp;m_twim, &amp;amp;xfer_desc, 0);
	//APP_ERROR_CHECK(status_code);

	// Reset the transmit buffer once it is clear the data was sent
	memset(tx_buff, 0, I2C_BUFF_SIZE);

#elif(0 == I2C_BLOCKING_MODE)

	memcpy(tx_buff, reg_data, loc_cnt);

	// Let the module know their is a transfer in progress
	m_xfer_done = false;

	// Define a transmit transfer descriptor to be used in the next twi transfer
	nrfx_twim_xfer_desc_t xfer_desc =
		NRFX_TWIM_XFER_DESC_TXTX(loc_slave_addr, &amp;amp;loc_reg_addr, 1, tx_buff, loc_cnt);

	// Transmit the register address and the data to be stored there. 
	do
	{
		status_code = nrfx_twim_xfer(&amp;amp;m_twim, &amp;amp;xfer_desc, 0);
		if(NRFX_ERROR_BUSY == status_code)
		{
			LOG_I2C(&amp;quot;Sending I2C message...\r\n&amp;quot;);
		}	/*	end if block	*/
	}while(NRFX_ERROR_BUSY == status_code);
	APP_ERROR_CHECK(status_code);

#endif

	return status_code;
}


int32_t twi_read(	void * p_dev_addr, uint8_t reg_addr, 
							uint8_t *reg_data, uint16_t cnt)
{ 
	ret_code_t status_code = NRF_SUCCESS;

	// Get the slave address
	static uint8_t loc_slave_addr 	= 0;
	static uint8_t loc_reg_addr 	= 0;
	static uint16_t loc_cnt 		= 0;

	// Don&amp;#39;t continue unless the previous transfer is complete
	while(false == m_xfer_done)
	{
		vTaskDelay(pdMS_TO_TICKS(1));
	}	/*	end while loop	*/

	// Update the local xfer data once the handler has finished
	loc_slave_addr 	= *(uint8_t*)p_dev_addr;
	loc_reg_addr 	= reg_addr;
	loc_cnt 		= cnt;

#if(1 == I2C_BLOCKING_MODE)
	/*	Define a transmit transfer descriptor to be used in the next twi 
		transfer. This only sends the register address	*/
	nrfx_twim_xfer_desc_t xfer_desc1 =
		NRFX_TWIM_XFER_DESC_TX(loc_slave_addr, &amp;amp;reg_addr, 1);
	
	/*	Send the register address with NO STOP! This is part of the I2C protocol
		on the LSM6DSOX and LIS2MDL chips.	*/
	status_code |= nrfx_twim_xfer(&amp;amp;m_twim, &amp;amp;xfer_desc1, NRFX_TWIM_FLAG_TX_NO_STOP);
	//APP_ERROR_CHECK(status_code);

	/*	Define a receive transfer descriptor to be used in the next twi 
		transfer.	*/
	nrfx_twim_xfer_desc_t xfer_desc2 = 
		NRFX_TWIM_XFER_DESC_RX(loc_slave_addr, rx_buff, cnt);

	/* This sends the slave address + read bit, and then receives
		the next cnt bytes.	*/
	status_code |= nrfx_twim_xfer(&amp;amp;m_twim, &amp;amp;xfer_desc2, 0);
	//APP_ERROR_CHECK(status_code);

#elif(0 == I2C_BLOCKING_MODE)

	// Let the module know their is a transfer in progress
	m_xfer_done = false;

	/*	Define a receive transfer descriptor to be used in the next twi 
		transfer.	*/
	nrfx_twim_xfer_desc_t xfer_desc = 
		NRFX_TWIM_XFER_DESC_TXRX(loc_slave_addr, &amp;amp;loc_reg_addr, 1, rx_buff, loc_cnt);

	/* This transfer will send the register byte and then receive the data from
		that register.	*/
	do
	{
		// The while allows for the data to not be passed over
		status_code = nrfx_twim_xfer(&amp;amp;m_twim, &amp;amp;xfer_desc, 0);
		if(NRFX_ERROR_BUSY == status_code)
		{
			LOG_I2C(&amp;quot;Receiving I2C message...\r\n&amp;quot;);
		}	/*	end if block	*/
	}while(NRFX_ERROR_BUSY == status_code);
	APP_ERROR_CHECK(status_code);

#endif


	/*	Copy the data received in the rx_buff from the last transfer to the
		buffer passed into this function	*/
	memcpy(reg_data, rx_buff, cnt);

	return status_code;
}

static void I2C_Evt_Handler(nrfx_twim_evt_t const * p_event, void * p_context)
{
	switch (p_event-&amp;gt;type)
	{
		case(NRFX_TWIM_EVT_DONE):
		{
			if(NRFX_TWIM_XFER_TXRX == p_event-&amp;gt;xfer_desc.type)
			{
				// Do nothing right now
			}	/*	end if block	*/
			else if(NRFX_TWIM_XFER_TXTX == p_event-&amp;gt;xfer_desc.type)
			{
				// Reset the transmit buffer once it is clear the data was sent
				memset(tx_buff, 0, I2C_BUFF_SIZE);
			}	/*	end else-if block	*/

			m_xfer_done = true;
			break;
		}	/*	end case block	*/
		case(NRFX_TWIM_EVT_ADDRESS_NACK):
		case(NRFX_TWIM_EVT_DATA_NACK):
		case(NRFX_TWIM_EVT_OVERRUN):
		case(NRFX_TWIM_EVT_BUS_ERROR):
		default:
		{
			LOG_I2C(&amp;quot;I2C Error Event: \r\naddress = %d\r\nprimary[0] = %d\r\n secondary[0] = %d\r\n&amp;quot;, 
			        p_event-&amp;gt;xfer_desc.address, p_event-&amp;gt;xfer_desc.p_primary_buf[0], 
			        p_event-&amp;gt;xfer_desc.p_secondary_buf[0]);
			break;
		}	/*	end case block	*/
	}	/*	end switch-case block	*/
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve taken out the extra stuff and tried to leave the important parts. The macro I2C_BLOCKING_MODE is what I am using to test the blocking/non-blocking modes. When I have it set to 1 (blocking mode enabled), then the configurations send correctly and a subsequent read from the same register shows that the TWI transfer was successful. When set to 0 (non-blocking mode enabled) however, the TWI transfer does not actually change the LIS2MDL configuration.&lt;/p&gt;
&lt;p&gt;Thanks for your help!&lt;/p&gt;
&lt;p&gt;Joseph&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: TWIM Errata 109</title><link>https://devzone.nordicsemi.com/thread/456878?ContentTypeID=1</link><pubDate>Wed, 22 Nov 2023 10:57:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8c44e354-38a3-4a71-b896-17e48f653f19</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello &lt;span&gt;Joseph&lt;/span&gt;,&lt;/p&gt;
&lt;p&gt;The timing conditions needed to trigger this errata usually makes it pretty hard to reproduce the DMA corruption&amp;nbsp;(official link:&amp;nbsp;&lt;a href="https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev3/ERR/nRF52832/Rev3/latest/anomaly_832_109.html?cp=5_2_1_0_1_31"&gt;[109] DMA: DMA access transfers might be corrupted&lt;/a&gt;). Also, the nRF52840 is not affected by this either. The errata is for the nRF52832.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Are you able to share relevant code snippets here or in a private ticket so I can try to review them?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Thanks,&lt;/p&gt;
&lt;p&gt;Vidar&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>