duparq / hwa

Header-only library for bare metal hardware programming in C with a pleasant generic style.
http://duparq.free.fr/hwa/index.html
Other
25 stars 4 forks source link

Feature Request: hw(turn, twi0, off); #2

Closed gotnone closed 4 years ago

gotnone commented 5 years ago

I have run into some issues with using the TWI bus and an ATMEGA 328p chip. Despite following the example provided for reading and writing to a TWI EEPROM, I have encountered some very strange states on the twi bus, including having the while( !hw(read, HW_IRQFLAG(TWI)) ) {} loop continuously, and even after putting a watchdog into that loop, the subsequent twst=hw(stat,TWI) returns the value HW_TWI_NO_INFO. Unfortunately, I don't have access to a logic analyzer or digital oscilloscope to see what exactly is wrong with the TWI bus communication. It does seem to be an occasional signal level issue on the bus. When the ATMEGA chip encouters these strange bus states it seems to corrupt its TWI state machine. Repeated attempts to send start or otherwise restart the TWI communication fail once the chip hits this state.

I added the following code to allow hw(turn, twi0, off); When I detect that the ATMEGA is in this corrupt state, I can disable the TWI engine and then reconfigure it with a hw or hwa(configure, twi0, ...); and then resume TWI communications. I don't think it is necessary to provide a turn on function as that is covered by the configure command.

I am no expert at macro programming and I probably did something boneheaded here, but it does seem to work to turn off the TWI engine. If I overlooked a different function that performs the same operation, please point it out to me.

diff --git a/atmel/avr/classes/twia_2.h b/atmel/avr/classes/twia_2.h
index 8f097e5..b9eda72 100644
--- a/atmel/avr/classes/twia_2.h
+++ b/atmel/avr/classes/twia_2.h
@@ -388,6 +388,23 @@
  */
 #define HW_TWI_BUS_ERROR               0x00

+/*      Turn TWI on / off
+ */
+#define _hw_turn_twia_(o,i,a, v, ...)                   \
+  HW_Y(_hwx_turn_twia_,_hw_state_##v)(_hw,o,v,__VA_ARGS__)
+
+#define _hwa_turn_twia_(o,i,a, v, ...)                  \
+  HW_Y(_hwx_turn_twia_,_hw_state_##v)(_hwa,o,v,__VA_ARGS__)
+
+#define _hwx_turn_twia__0(x,o, v, ...)                  \
+  HW_E_ST(v)
+
+#define _hwx_turn_twia__1(x,o, v, ...)                                  \
+  HW_TX(x##_write_reg(o, en, HW_A1(_hw_state_##v)),__VA_ARGS__)
+
+#define _hw_mtd_hw_turn__twia          , _hw_turn_twia_
+
+#define _hw_mtd_hwa_turn__twia , _hwa_turn_twia_

 /*******************************************************************************
duparq commented 5 years ago

Thank you for your contribution. I've merged your code. It is all the more pleasant seeing someone write new stuff for HWA that it is not that simple! About the strange behavior you observed, have you tried turning the TWI on before sending anything on the bus? I've just realized that the 'configure' action does not enable the TWI.

gotnone commented 4 years ago

Thanks for fixing this so promptly. I forgot the issue was left open. I went back and looked at my code. I did turn on the TWI engine and then configured it. I believe that part of my issue actually stemmed from some dodgy wiring to the TWI slave on my prototype. Having the ability to reset the TWI engine was critical to getting further on the project.