59
59
#include "app_util_platform.h"
60
60
#include "prs/nrfx_prs.h"
61
61
62
+ #if DEVICE_I2CSLAVE
63
+ #include "nrfx_twis.h"
64
+ #endif
65
+
62
66
#define TWI_PIN_INIT (_pin ) nrf_gpio_cfg((_pin), \
63
67
NRF_GPIO_PIN_DIR_INPUT, \
64
68
NRF_GPIO_PIN_INPUT_CONNECT, \
@@ -91,6 +95,18 @@ typedef enum {
91
95
NORDIC_TWI_STATE_BUSY
92
96
} nordic_nrf5_twi_state_t ;
93
97
98
+ #if DEVICE_I2CSLAVE
99
+
100
+ /* To properly uninitialize the last-used driver, we need to know if
101
+ * it was a master (nrfx_twi_...) or a slave (nrfx_twis_...)
102
+ */
103
+ typedef enum {
104
+ NORDIC_TWI_INITIALIZED_AS_MASTER ,
105
+ NORDIC_TWI_INITIALIZED_AS_SLAVE ,
106
+ NORDIC_TWI_UNINITIALIZED
107
+ } nordic_nrf5_twi_slave_state_t ;
108
+ #endif
109
+
94
110
/* Forward declaration. These functions are implemented in the driver but not
95
111
* set up in the NVIC due to it being relocated.
96
112
*/
@@ -135,6 +151,15 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
135
151
config -> mask = 0 ;
136
152
#endif
137
153
154
+ #if DEVICE_I2CSLAVE
155
+ /** was_slave is used to decide which driver call we need
156
+ * to use when uninitializing a given instance
157
+ */
158
+ config -> was_slave = false;
159
+ config -> is_slave = false;
160
+ config -> slave_addr = 0 ;
161
+ #endif
162
+
138
163
/* Force reconfiguration */
139
164
config -> update = true;
140
165
@@ -164,6 +189,14 @@ void i2c_frequency(i2c_t *obj, int hz)
164
189
struct i2c_s * config = obj ;
165
190
#endif
166
191
192
+
193
+ #if DEVICE_I2CSLAVE
194
+ /* Slaves automatically get frequency from master, may be 100kHz or 400kHz */
195
+ if (config -> is_slave ) {
196
+ return ;
197
+ }
198
+ #endif
199
+
167
200
/* Round down to nearest valid frequency. */
168
201
nrf_twi_frequency_t new_frequency ;
169
202
@@ -588,6 +621,10 @@ void i2c_reset(i2c_t *obj)
588
621
/* Global array holding driver configuration for easy access. */
589
622
static const nrfx_twi_t nordic_nrf5_instance [2 ] = { NRFX_TWI_INSTANCE (0 ), NRFX_TWI_INSTANCE (1 ) };
590
623
624
+ #if DEVICE_I2CSLAVE
625
+ static const nrfx_twis_t nordic_nrf5_twis_instance [2 ] = { NRFX_TWIS_INSTANCE (0 ), NRFX_TWIS_INSTANCE (1 ) };
626
+ #endif
627
+
591
628
/* Forward declare interrupt handler. */
592
629
#if DEVICE_I2C_ASYNCH
593
630
static void nordic_nrf5_twi_event_handler (nrfx_twi_evt_t const * p_event , void * p_context );
@@ -632,51 +669,90 @@ static void i2c_configure_driver_instance(i2c_t *obj)
632
669
633
670
/* If the peripheral is already running, then disable it and use the driver API to uninitialize it.*/
634
671
if (nordic_nrf5_instance [instance ].p_twi -> ENABLE ) {
672
+ #if DEVICE_I2CSLAVE
673
+ /* If it was a slave, we should disable it with the appropriate driver */
674
+ if (config -> was_slave ) {
675
+ nrfx_twis_disable (& nordic_nrf5_twis_instance [instance ]);
676
+ nrfx_twis_uninit (& nordic_nrf5_twis_instance [instance ]);
677
+ }
678
+ else {
635
679
nrfx_twi_disable (& nordic_nrf5_instance [instance ]);
636
680
nrfx_twi_uninit (& nordic_nrf5_instance [instance ]);
637
681
}
638
682
683
+ #else
684
+ nrfx_twi_disable (& nordic_nrf5_instance [instance ]);
685
+ nrfx_twi_uninit (& nordic_nrf5_instance [instance ]);
686
+ #endif
687
+
688
+ }
689
+
639
690
/* Force resource release. This is necessary because mbed drivers don't
640
691
* deinitialize on object destruction.
641
692
*/
642
693
NRFX_IRQ_DISABLE ((nrfx_get_irq_number ((void const * )nordic_nrf5_twi_register [instance ])));
643
694
644
- /* Configure driver with new settings. */
645
- nrfx_twi_config_t twi_config = {
646
- .scl = config -> scl ,
647
- .sda = config -> sda ,
648
- .frequency = config -> frequency ,
649
- .interrupt_priority = APP_IRQ_PRIORITY_LOWEST ,
650
- .hold_bus_uninit = false
651
- };
695
+ #if DEVICE_I2CSLAVE
696
+ if (config -> is_slave ) {
697
+ /* Configure driver as slave with new settings. */
698
+ nrfx_twis_config_t twis_config = {
699
+ .addr = { (config -> slave_addr >> 1 ), 0 },
700
+ .scl = config -> scl ,
701
+ .sda = config -> sda ,
702
+ .scl_pull = NRF_GPIO_PIN_NOPULL ,
703
+ .sda_pull = NRF_GPIO_PIN_NOPULL ,
704
+ .interrupt_priority = APP_IRQ_PRIORITY_LOWEST
705
+ };
706
+ /* Initialze driver in blocking mode. */
707
+ nrfx_twis_init (& nordic_nrf5_twis_instance [instance ],
708
+ & twis_config ,
709
+ NULL );
652
710
653
- #if DEVICE_I2C_ASYNCH
654
- /* Set callback handler in asynchronous mode. */
655
- if (config -> handler ) {
711
+ /* Enable peripheral (nrfx_twi_t and nrfx_twis_t are interchangeable). */
712
+ nrfx_twis_enable (& nordic_nrf5_twis_instance [instance ]);
713
+ }
714
+ else {
715
+ #endif
656
716
657
- /* Initialze driver in non-blocking mode. */
658
- nrfx_twi_init (& nordic_nrf5_instance [instance ],
659
- & twi_config ,
660
- nordic_nrf5_twi_event_handler ,
661
- obj );
662
- } else {
717
+ /* Configure driver with new settings. */
718
+ nrfx_twi_config_t twi_config = {
719
+ .scl = config -> scl ,
720
+ .sda = config -> sda ,
721
+ .frequency = config -> frequency ,
722
+ .interrupt_priority = APP_IRQ_PRIORITY_LOWEST ,
723
+ .hold_bus_uninit = false
724
+ };
663
725
726
+ #if DEVICE_I2C_ASYNCH
727
+ /* Set callback handler in asynchronous mode. */
728
+ if (config -> handler ) {
729
+
730
+ /* Initialze driver in non-blocking mode. */
731
+ nrfx_twi_init (& nordic_nrf5_instance [instance ],
732
+ & twi_config ,
733
+ nordic_nrf5_twi_event_handler ,
734
+ obj );
735
+ } else {
736
+
737
+ /* Initialze driver in blocking mode. */
738
+ nrfx_twi_init (& nordic_nrf5_instance [instance ],
739
+ & twi_config ,
740
+ NULL ,
741
+ NULL );
742
+ }
743
+ #else
664
744
/* Initialze driver in blocking mode. */
665
745
nrfx_twi_init (& nordic_nrf5_instance [instance ],
666
746
& twi_config ,
667
747
NULL ,
668
748
NULL );
669
- }
670
- #else
671
- /* Initialze driver in blocking mode. */
672
- nrfx_twi_init (& nordic_nrf5_instance [instance ],
673
- & twi_config ,
674
- NULL ,
675
- NULL );
676
749
#endif
677
750
678
- /* Enable peripheral. */
679
- nrfx_twi_enable (& nordic_nrf5_instance [instance ]);
751
+ /* Enable peripheral. */
752
+ nrfx_twi_enable (& nordic_nrf5_instance [instance ]);
753
+ #if DEVICE_I2CSLAVE
754
+ }
755
+ #endif
680
756
}
681
757
}
682
758
@@ -945,7 +1021,6 @@ void i2c_abort_asynch(i2c_t *obj)
945
1021
#endif // DEVICE_I2C_ASYNCH
946
1022
947
1023
#if DEVICE_I2CSLAVE
948
- #warning DEVICE_I2CSLAVE
949
1024
950
1025
/***
951
1026
* _____ ___ _____ _____ _
@@ -965,6 +1040,25 @@ void i2c_abort_asynch(i2c_t *obj)
965
1040
*/
966
1041
void i2c_slave_mode (i2c_t * obj , int enable_slave )
967
1042
{
1043
+ #if DEVICE_I2C_ASYNCH
1044
+ struct i2c_s * config = & obj -> i2c ;
1045
+ #else
1046
+ struct i2c_s * config = obj ;
1047
+ #endif
1048
+
1049
+ /* Reconfigure this instance as an I2C slave */
1050
+
1051
+ /* Not configured yet, so this instance is and was a slave */
1052
+ if (config -> state == NRFX_DRV_STATE_UNINITIALIZED ) {
1053
+ config -> was_slave = enable_slave ;
1054
+ } else {
1055
+ config -> was_slave = config -> is_slave ;
1056
+ }
1057
+ config -> is_slave = enable_slave ;
1058
+ config -> update = true;
1059
+
1060
+ i2c_configure_driver_instance (obj );
1061
+
968
1062
DEBUG_PRINTF ("i2c_slave_mode\r\n" );
969
1063
}
970
1064
@@ -977,6 +1071,22 @@ int i2c_slave_receive(i2c_t *obj)
977
1071
{
978
1072
DEBUG_PRINTF ("i2c_slave_receive\r\n" );
979
1073
1074
+ #if DEVICE_I2C_ASYNCH
1075
+ struct i2c_s * config = & obj -> i2c ;
1076
+ #else
1077
+ struct i2c_s * config = obj ;
1078
+ #endif
1079
+
1080
+ const nrfx_twis_t * twis_instance = & nordic_nrf5_twis_instance [config -> instance ];
1081
+
1082
+ if (nrfx_twis_is_waiting_rx_buff (twis_instance )) {
1083
+ return 3 ;
1084
+ }
1085
+
1086
+ if (nrfx_twis_is_waiting_tx_buff (twis_instance )) {
1087
+ return 1 ;
1088
+ }
1089
+
980
1090
return 0 ;
981
1091
}
982
1092
@@ -990,7 +1100,26 @@ int i2c_slave_read(i2c_t *obj, char *data, int length)
990
1100
{
991
1101
DEBUG_PRINTF ("i2c_slave_read\r\n" );
992
1102
993
- return 0 ;
1103
+ #if DEVICE_I2C_ASYNCH
1104
+ struct i2c_s * config = & obj -> i2c ;
1105
+ #else
1106
+ struct i2c_s * config = obj ;
1107
+ #endif
1108
+
1109
+ const nrfx_twis_t * twis_instance = & nordic_nrf5_twis_instance [config -> instance ];
1110
+
1111
+ /* Wait until the master is trying to write data */
1112
+ while (!nrfx_twis_is_waiting_rx_buff (twis_instance )) { }
1113
+
1114
+ /* Master is attempting to write, now we prepare the rx buffer */
1115
+ nrfx_twis_rx_prepare (twis_instance ,
1116
+ data ,
1117
+ length );
1118
+
1119
+ /* Wait until the transaction is over */
1120
+ while (nrfx_twis_is_pending_rx (twis_instance )) { }
1121
+
1122
+ return nrfx_twis_rx_amount (twis_instance );
994
1123
}
995
1124
996
1125
/** Configure I2C as slave or master.
@@ -1003,7 +1132,26 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length)
1003
1132
{
1004
1133
DEBUG_PRINTF ("i2c_slave_write\r\n" );
1005
1134
1006
- return 0 ;
1135
+ #if DEVICE_I2C_ASYNCH
1136
+ struct i2c_s * config = & obj -> i2c ;
1137
+ #else
1138
+ struct i2c_s * config = obj ;
1139
+ #endif
1140
+
1141
+ const nrfx_twis_t * twis_instance = & nordic_nrf5_twis_instance [config -> instance ];
1142
+
1143
+ /* Wait until the master is trying to read data */
1144
+ while (!nrfx_twis_is_waiting_tx_buff (twis_instance )) { }
1145
+
1146
+ /* Master is attempting to read, now we prepare the tx buffer */
1147
+ nrfx_twis_tx_prepare (twis_instance ,
1148
+ data ,
1149
+ length );
1150
+
1151
+ /* Wait until the transaction is over */
1152
+ while (nrfx_twis_is_pending_tx (twis_instance )) { }
1153
+
1154
+ return nrfx_twis_tx_amount (twis_instance );
1007
1155
}
1008
1156
1009
1157
/** Configure I2C address.
@@ -1014,6 +1162,18 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length)
1014
1162
*/
1015
1163
void i2c_slave_address (i2c_t * obj , int idx , uint32_t address , uint32_t mask )
1016
1164
{
1165
+ #if DEVICE_I2C_ASYNCH
1166
+ struct i2c_s * config = & obj -> i2c ;
1167
+ #else
1168
+ struct i2c_s * config = obj ;
1169
+ #endif
1170
+
1171
+ /* Reconfigure this instance as an I2C slave with given address */
1172
+ config -> update = true;
1173
+ config -> slave_addr = (uint8_t ) address ;
1174
+
1175
+ i2c_configure_driver_instance (obj );
1176
+
1017
1177
DEBUG_PRINTF ("i2c_slave_address\r\n" );
1018
1178
}
1019
1179
0 commit comments