@@ -92,6 +92,8 @@ Pin watchedPins[16];
9292
9393// Whether a pin is being used for soft PWM or not
9494BITFIELD_DECL (jshPinSoftPWM , JSH_PIN_COUNT );
95+ // Whether a pin is being used for hard PWM or not
96+ BITFIELD_DECL (jshPinHardPWM , JSH_PIN_COUNT );
9597
9698#ifdef STM32F1
9799// F1 can't do opendrain pullup, so we do it manually!
@@ -135,6 +137,12 @@ void jshSetIsSerial7Bit(IOEventFlags device, bool is7Bit) {
135137}
136138#endif
137139
140+ bool jshIsHWPWMActive () {
141+ for (unsigned int i = 0 ;i < (sizeof (jshPinHardPWM )>>2 );i ++ ) // it's a uint32
142+ if (jshPinHardPWM [i ]) return true;
143+ return false;
144+ }
145+
138146// ----------------------------------------------------------------------------
139147// PINS
140148
@@ -958,14 +966,12 @@ void jshDelayMicroseconds(int microsec) {
958966 while (iter -- ) __NOP ();
959967}
960968
961- void jshPinSetState (Pin pin , JshPinState state ) {
969+ /// Internal implementation (does not call jshPinUpdateFunction as this is itself called from jshPinSetFunction)
970+ static void jshPinSetState_intl (Pin pin , JshPinState state ) {
962971 if (pinInfo [pin ].port & JSH_PIN_NEGATED ) {
963972 if (state == JSHPINSTATE_GPIO_IN_PULLUP ) state = JSHPINSTATE_GPIO_IN_PULLDOWN ;
964973 else if (state == JSHPINSTATE_GPIO_IN_PULLDOWN ) state = JSHPINSTATE_GPIO_IN_PULLUP ;
965974 }
966- // if this is about to mess up the neopixel output, so reset our var so we know to re-init
967- if (pin == jshNeoPixelPin )
968- jshNeoPixelPin = PIN_UNDEFINED ;
969975 /* Make sure we kill software PWM if we set the pin state
970976 * after we've started it */
971977 if (BITFIELD_GET (jshPinSoftPWM , pin )) {
@@ -1057,21 +1063,31 @@ JshPinState jshPinGetState(Pin pin) {
10571063 // GPIO_ReadOutputDataBit(port, pinn);
10581064}
10591065
1066+ static NO_INLINE void jshPinUpdateFunction (Pin pin , JshPinFunction func ) {
1067+ // keep track of whether we are doing PWM or not
1068+ if (JSH_PINFUNCTION_IS_TIMER (func )) {
1069+ BITFIELD_SET (jshPinHardPWM , pin , true);
1070+ } else {
1071+ BITFIELD_SET (jshPinHardPWM , pin , false);
1072+ }
1073+ }
1074+
10601075static NO_INLINE void jshPinSetFunction (Pin pin , JshPinFunction func ) {
1076+ jshPinUpdateFunction (pin , func );
10611077 if (JSH_PINFUNCTION_IS_USART (func )) {
10621078 if ((func & JSH_MASK_INFO )== JSH_USART_RX )
1063- jshPinSetState (pin , JSHPINSTATE_USART_IN );
1079+ jshPinSetState_intl (pin , JSHPINSTATE_USART_IN );
10641080 else
1065- jshPinSetState (pin ,JSHPINSTATE_USART_OUT );
1081+ jshPinSetState_intl (pin , JSHPINSTATE_USART_OUT );
10661082 } else if (JSH_PINFUNCTION_IS_I2C (func )) {
1067- jshPinSetState (pin , JSHPINSTATE_I2C );
1083+ jshPinSetState_intl (pin , JSHPINSTATE_I2C );
10681084#ifdef STM32F1 // F4 needs SPI MOSI to be set as AF out
10691085 } else if (JSH_PINFUNCTION_IS_SPI (func ) && ((func & JSH_MASK_INFO )== JSH_SPI_MISO )) {
1070- jshPinSetState (pin , JSHPINSTATE_GPIO_IN_PULLUP ); // input pullup for MISO
1086+ jshPinSetState_intl (pin , JSHPINSTATE_GPIO_IN_PULLUP ); // input pullup for MISO
10711087#endif
10721088 } else {
10731089 bool opendrain = JSHPINSTATE_IS_OPENDRAIN (jshPinGetState (pin )& JSHPINSTATE_MASK );
1074- jshPinSetState (pin , opendrain ? JSHPINSTATE_AF_OUT_OPENDRAIN : JSHPINSTATE_AF_OUT ); // otherwise general AF out!
1090+ jshPinSetState_intl (pin , opendrain ? JSHPINSTATE_AF_OUT_OPENDRAIN : JSHPINSTATE_AF_OUT ); // otherwise general AF out!
10751091 }
10761092 // now 'connect' the pin up
10771093#if defined(STM32F2 ) || defined(STM32F3 ) || defined(STM32F4 )
@@ -1108,10 +1124,16 @@ static NO_INLINE void jshPinSetFunction(Pin pin, JshPinFunction func) {
11081124 }
11091125#endif
11101126 else if (remap ) jsError ("(internal) Remap needed, but unknown device %d" , func & JSH_MASK_TYPE );
1111-
11121127#endif
11131128}
11141129
1130+ void jshPinSetState (Pin pin , JshPinState state ) {
1131+ // If this was set to be some kind of AF (USART, etc), reset it.
1132+ jshPinUpdateFunction (pin , JSH_NOTHING );
1133+ // Now set the state properly
1134+ jshPinSetState_intl (pin , state );
1135+ }
1136+
11151137void jshPinSetValue (Pin pin , bool value ) {
11161138 if (pinInfo [pin ].port & JSH_PIN_NEGATED ) value = !value ;
11171139#ifdef STM32API2
@@ -1244,7 +1266,7 @@ void jshInit() {
12441266 we detect that (with RTC_BKP_DR0_TURN_OFF written into RTC_BKP_DR0) and turn ourselves back off quickly */
12451267 if (RTC_ReadBackupRegister (RTC_BKP_DR0 )== RTC_BKP_DR0_TURN_OFF ) {
12461268 PWR_BackupAccessCmd (ENABLE );
1247- jshDelayMicroseconds (10 ); // Some devices seem to need a delay
1269+ jshDelayMicroseconds (10 ); // Some devices seem to need a delay
12481270 RTC_WriteBackupRegister (RTC_BKP_DR0 , RTC_BKP_DR0_NULL );
12491271 if (RCC_GetFlagStatus (RCC_FLAG_IWDGRST )) {
12501272 PWR_WakeUpPinCmd (ENABLE );
@@ -1265,6 +1287,7 @@ void jshInit() {
12651287 for (i = 0 ;i < 16 ;i ++ )
12661288 watchedPins [i ] = PIN_UNDEFINED ;
12671289 BITFIELD_CLEAR (jshPinSoftPWM );
1290+ BITFIELD_CLEAR (jshPinHardPWM );
12681291#ifdef STM32F1
12691292 BITFIELD_CLEAR (jshPinOpendrainPullup );
12701293#endif
@@ -2209,10 +2232,9 @@ void *NO_INLINE checkPinsForDevice(JshPinFunction device, int count, Pin *pins,
22092232 void * ptr = setDeviceClockCmd (device , ENABLE );
22102233 // now set up correct states
22112234 for (i = 0 ;i < count ;i ++ )
2212- if (jshIsPinValid (pins [i ])) {
2213- //pinState[pins[i]] = functions[i];
2214- jshPinSetFunction (pins [i ], functions [i ]);
2215- }
2235+ if (jshIsPinValid (pins [i ])) {
2236+ jshPinSetFunction (pins [i ], functions [i ]);
2237+ }
22162238 // all ok
22172239 return ptr ;
22182240}
@@ -2706,7 +2728,6 @@ bool jshSleep(JsSysTime timeUntilWake) {
27062728 /* TODO:
27072729 Check jsiGetConsoleDevice to make sure we don't have to wake on USART (we can't do this fast enough)
27082730 Check that we're not using EXTI 11 for something else
2709- Check we're not using PWM as this will stop
27102731 What about EXTI line 18 - USB Wakeup event
27112732 Check time until wake against where we are in the RTC counter - we can sleep for 0.1 sec if we're 90% of the way through the counter...
27122733 */
@@ -2717,6 +2738,7 @@ bool jshSleep(JsSysTime timeUntilWake) {
27172738 (timeUntilWake > (jshGetTimeForSecond ()* 16 * 2 /jshRTCPrescaler )) && // if there's less time that this then we can't go to sleep because we can't be sure we'll wake in time
27182739#endif
27192740 !jstUtilTimerIsRunning () && // if the utility timer is running (eg. digitalPulse, Waveform output, etc) then that would stop so we can't sleep
2741+ !jshIsHWPWMActive () && // Check we're not using PWM as this will stop
27202742 !jshHasTransmitData () && // if we're transmitting, we don't want USART/etc to get slowed down
27212743#ifdef USB
27222744 !USB_IsConnected () &&
@@ -3343,5 +3365,17 @@ void jshReboot() {
33433365/* Adds the estimated power usage of the microcontroller in uA to the 'devices' object. The CPU should be called 'CPU' */
33443366void jsvGetProcessorPowerUsage (JsVar * devices ) {
33453367 jsvObjectSetChildAndUnLock (devices , "CPU" , jsvNewFromInteger (15000 ));
3368+ if (jshIsHWPWMActive ()) {
3369+ jsvObjectSetChildAndUnLock (devices , "PWM" , jsvNewFromInteger (1000 )); // Guess
3370+ // report names of pins with PWM to aid debugging
3371+ char pwmPin [13 ] = "PWM" ;
3372+ for (Pin i = 0 ;i < JSH_PIN_COUNT ;i ++ ) {
3373+ if (BITFIELD_GET (jshPinHardPWM ,i )) {
3374+ jshGetPinString (& pwmPin [3 ], i );
3375+ jsvObjectSetChildAndUnLock (devices , pwmPin , jsvNewFromInteger (0 ));
3376+ }
3377+ }
3378+ }
33463379 // we're not in deep sleep now (should we be able to figure out how long we were sleeping for?)
33473380}
3381+
0 commit comments