@@ -162,10 +162,19 @@ void pin_mode(PinName pin, PinMode mode)
162162
163163 uint32_t port_index = STM_PORT (pin );
164164 uint32_t pin_index = STM_PIN (pin );
165-
166165 // Enable GPIO clock
167166 uint32_t gpio_add = Set_GPIO_Clock (port_index );
168167 GPIO_TypeDef * gpio = (GPIO_TypeDef * )gpio_add ;
168+ __IO uint32_t * gpio_reg_hl ;//gpio register depends on bit index (high or low)
169+ uint32_t shift ;
170+
171+ if (pin_index < 8 ) {
172+ shift = (pin_index * 4 );
173+ gpio_reg_hl = & (gpio -> CRL );
174+ } else {
175+ shift = (pin_index % 8 ) * 4 ;
176+ gpio_reg_hl = & (gpio -> CRH );
177+ }
169178
170179 // Configure open-drain and pull-up/down
171180 switch (mode ) {
@@ -174,16 +183,9 @@ void pin_mode(PinName pin, PinMode mode)
174183 case PullUp :
175184 case PullDown :
176185 // Set pull-up / pull-down for Input mode
177- if (pin_index < 8 ) {
178- if ((gpio -> CRL & (0x03 << (pin_index * 4 ))) == 0 ) { // MODE bits = Input mode
179- gpio -> CRL |= (0x08 << (pin_index * 4 )); // Set pull-up / pull-down
180- gpio -> CRL &= ~(0x04 << (pin_index * 4 )); // ENSURES GPIOx_CRL.CNFx.bit0 = 0
181- }
182- } else {
183- if ((gpio -> CRH & (0x03 << ((pin_index % 8 ) * 4 ))) == 0 ) { // MODE bits = Input mode
184- gpio -> CRH |= (0x08 << ((pin_index % 8 ) * 4 )); // Set pull-up / pull-down
185- gpio -> CRH &= ~(0x04 << ((pin_index % 8 ) * 4 )); // ENSURES GPIOx_CRH.CNFx.bit0 = 0
186- }
186+ if ((* gpio_reg_hl & (0x03 << shift )) == 0 ) { // MODE bits = Input mode
187+ * gpio_reg_hl |= (0x08 << shift ); // Set pull-up / pull-down
188+ * gpio_reg_hl &= ~(0x04 << shift ); // ENSURES GPIOx_CRL.CNFx.bit0 = 0
187189 }
188190 // Now it's time to setup properly if pullup or pulldown. This is done in ODR register:
189191 // set pull-up => bit=1, set pull-down => bit = 0
@@ -195,17 +197,51 @@ void pin_mode(PinName pin, PinMode mode)
195197 break ;
196198 case OpenDrain :
197199 // Set open-drain for Output mode (General Purpose or Alternate Function)
198- if (pin_index < 8 ) {
199- if ((gpio -> CRL & (0x03 << (pin_index * 4 ))) > 0 ) { // MODE bits = Output mode
200- gpio -> CRL |= (0x04 << (pin_index * 4 )); // Set open-drain
201- }
202- } else {
203- if ((gpio -> CRH & (0x03 << ((pin_index % 8 ) * 4 ))) > 0 ) { // MODE bits = Output mode
204- gpio -> CRH |= (0x04 << ((pin_index % 8 ) * 4 )); // Set open-drain
205- }
200+ if ((* gpio_reg_hl & (0x03 << shift )) > 0 ) { // MODE bits = Output mode
201+ * gpio_reg_hl |= (0x04 << shift ); // Set open-drain
206202 }
207203 break ;
208204 default :
209205 break ;
210206 }
211207}
208+
209+ /* Internal function for setting the gpiomode/function
210+ * without changing Pull mode
211+ */
212+ void pin_function_gpiomode (PinName pin , uint32_t gpiomode ) {
213+
214+ /* Read current pull state from HW to avoid over-write*/
215+ uint32_t port_index = STM_PORT (pin );
216+ uint32_t pin_index = STM_PIN (pin );
217+ GPIO_TypeDef * gpio = (GPIO_TypeDef * ) Set_GPIO_Clock (port_index );
218+ uint32_t pull = PullNone ;
219+ __IO uint32_t * gpio_reg_hl ;//gpio register depends on bit index (high or low)
220+ uint32_t shift ;
221+
222+ if (pin_index < 8 ) {
223+ shift = (pin_index * 4 );
224+ gpio_reg_hl = & (gpio -> CRL );
225+ } else {
226+ shift = (pin_index % 8 ) * 4 ;
227+ gpio_reg_hl = & (gpio -> CRH );
228+ }
229+
230+ /* Check if pull/pull down is active */
231+ if ((!(* gpio_reg_hl & (0x03 << shift ))) // input
232+ && (!!(* gpio_reg_hl & (0x08 << shift ))) // pull-up / down
233+ && (!(* gpio_reg_hl & (0x04 << shift )))) { // GPIOx_CRL.CNFx.bit0 = 0
234+ if (!!(gpio -> ODR & (0x01 << pin_index ))) {
235+ pull = PullUp ;
236+ } else {
237+ pull = PullDown ;
238+ }
239+ } else { //output
240+ if (!!(* gpio_reg_hl & (0x04 << shift ))) { //open drain
241+ pull = OpenDrain ;
242+ }
243+ }
244+
245+ /* Then re-use global function for updating the mode part*/
246+ pin_function (pin , STM_PIN_DATA (gpiomode , pull , 0 ));
247+ }
0 commit comments