<?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>Pwm Stays on even when proper stop functions are called</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/68522/pwm-stays-on-even-when-proper-stop-functions-are-called</link><description>Hello, 
 
 I am running an application on the s140 soft device using the buttonless dfu as an example. I am using the dual ramp pwm scheme to generate complementary pwm waveforms for a DC-DC converter. This works great for me but I am running into an</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 19 Nov 2020 20:37:43 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/68522/pwm-stays-on-even-when-proper-stop-functions-are-called" /><item><title>RE: Pwm Stays on even when proper stop functions are called</title><link>https://devzone.nordicsemi.com/thread/280988?ContentTypeID=1</link><pubDate>Thu, 19 Nov 2020 20:37:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8d43777d-8cb8-4ae8-b871-ddd1d46572f5</guid><dc:creator>Austin Fox</dc:creator><description>&lt;p&gt;Thank you for this suggestion. I will give it a go. This makes sense to me. Didn&amp;#39;t know there was an issue with having only 1 entry in the pwm table. I appreciate your help with this.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Pwm Stays on even when proper stop functions are called</title><link>https://devzone.nordicsemi.com/thread/280728?ContentTypeID=1</link><pubDate>Thu, 19 Nov 2020 00:56:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6eca14e8-8db3-4301-bd28-e2c53bcd8474</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;It&amp;#39;s a little hard to help as I now only use low-level drivers and not the Nordic libraries; also you might use the &lt;em&gt;Insert-&amp;gt;Code-&amp;gt;C&lt;/em&gt; when posting code to make it easier to read, like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;   pNRF_PWM-&amp;gt;SHORTS = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;So here you can see I use a different SHORTS, but also I have more than 1 entry in my sequence. Using waveform mode allows a table, in this case a table of entries for the two pins non-overlapping and out-of-phase, then there can be more than just a value of 1 entry (the table lines can repeat).&lt;/p&gt;
&lt;p&gt;Something like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;//  DECODER.LOAD = Repeat
//  =====================
//  Charge PWM with Nordic library code
//
//   +----------------------------------&amp;gt; COMP0 OUT[0] Compare 0 - PIN_PWM_1
//   |         +------------------------&amp;gt; COMP1 OUT[1] Compare 1 - PIN_PWM_2
//   |         |         +--------------&amp;gt; COMP2 OUT[2] Compare 2 - spare
//   |         |         |               (COMP3 OUT[3] Compare 3 not used)
//   |         |         |
// +---------+---------+---------+---------+
// | Compare | Compare | Compare | Top     | Cycle N
// +---------+---------+---------+---------+
// | Compare | Compare | Compare | Top     | Cycle N+1
// +---------+---------+---------+---------+
//                                 |
//                                 +----&amp;gt; COUNTERTOP Cycle Period 4 steps, 1MHz clocks. Range 3-32767&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Which gives this waveform:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;//
//           |&amp;lt;------------- Charge Cycle 1 -----------&amp;gt;|&amp;lt;------------- Charge Cycle 2 --------&amp;gt;|
//           |                                          |                                       |
//           |&amp;lt;---- Chan 0 ----&amp;gt;| |&amp;lt;------ Chan 1 --&amp;gt;|  |&amp;lt;---- Chan 0 ----&amp;gt;| |&amp;lt;------ Chan 1 --&amp;gt;|
//           |                  | |                  |  |                  |                    |
//           |                  | |                  |  |                  |                    |
//           |               --&amp;gt;| |&amp;lt;-Dead-band A  --&amp;gt;|  |&amp;lt;-Dead-band B     |                    |
//           |                  | |                  |  |                  |                    |
//                                |                  |                     |
//           +==================+ |                  |  +================+ |                    +=
//           |                  | |                  |  |                | |                    |
//  PWM-1    |  Phase 1         |                       |     Phase 1    |                      |
// ==========+                  +=======================+                +======================+
//                                |                  |                     |
//
//                                +==================+                     +=================+
//                                |                  |                     |                 |
//  PWM-2                         |   Phase 2        |                     |   Phase 2       |
// ===============================+                  +=====================+                 +====&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This avoids the errata issue since there is more than 1 entry in the sequence table. Something like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;nrf_pwm_values_wave_form_t PWM_StepTable[] = {
 //   Index   PIN-PWM-1       PIN-PWM-2  PIN-SPARE Top Value
 //   =====   =============== =========  ========= ============
 { /*   0  */ (0x8000 | HIA), (LIA),     TOP,      TOP },
 { /*   1  */ (0x8000 | HIA), (LIA),     TOP,      TOP },
};&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Pwm Stays on even when proper stop functions are called</title><link>https://devzone.nordicsemi.com/thread/280725?ContentTypeID=1</link><pubDate>Thu, 19 Nov 2020 00:06:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d09203fc-cbc8-4a89-a092-a84f569c3a9e</guid><dc:creator>Austin Fox</dc:creator><description>&lt;p&gt;Looks like I am using this. I am using the nrfx_pwm_simple_playback function and passing in NRFX_PWM_FLAG_LOOP as I pulled this from an exapmle.&lt;/p&gt;
&lt;p&gt;Here is the function I am using.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;uint32_t nrfx_pwm_simple_playback(nrfx_pwm_t const * const p_instance,&lt;br /&gt; nrf_pwm_sequence_t const * p_sequence,&lt;br /&gt; uint16_t playback_count,&lt;br /&gt; uint32_t flags)&lt;br /&gt;{&lt;br /&gt; pwm_control_block_t * p_cb = &amp;amp;m_cb[p_instance-&amp;gt;drv_inst_idx];&lt;br /&gt; NRFX_ASSERT(p_cb-&amp;gt;state != NRFX_DRV_STATE_UNINITIALIZED);&lt;br /&gt; NRFX_ASSERT(playback_count &amp;gt; 0);&lt;br /&gt; NRFX_ASSERT(nrfx_is_in_ram(p_sequence-&amp;gt;values.p_raw));&lt;/p&gt;
&lt;p&gt;// To take advantage of the looping mechanism, we need to use both sequences&lt;br /&gt; // (single sequence can be played back only once).&lt;br /&gt; nrf_pwm_sequence_set(p_instance-&amp;gt;p_registers, 0, p_sequence);&lt;br /&gt; nrf_pwm_sequence_set(p_instance-&amp;gt;p_registers, 1, p_sequence);&lt;br /&gt; bool odd = (playback_count &amp;amp; 1);&lt;br /&gt; nrf_pwm_loop_set(p_instance-&amp;gt;p_registers,&lt;br /&gt; (playback_count / 2) + (odd ? 1 : 0));&lt;/p&gt;
&lt;p&gt;uint32_t shorts_mask;&lt;br /&gt; if (flags &amp;amp; NRFX_PWM_FLAG_STOP)&lt;br /&gt; {&lt;br /&gt; shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;&lt;br /&gt; }&lt;br /&gt; &lt;strong&gt;else if (flags &amp;amp; NRFX_PWM_FLAG_LOOP)&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt; {&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt; shorts_mask = odd ? NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt; : NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt; }&lt;/strong&gt;&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt; shorts_mask = 0;&lt;br /&gt; }&lt;br /&gt; &lt;strong&gt;nrf_pwm_shorts_set(p_instance-&amp;gt;p_registers, shorts_mask);&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;NRFX_LOG_INFO(&amp;quot;Function: %s, sequence length: %d.&amp;quot;,&lt;br /&gt; __func__,&lt;br /&gt; p_sequence-&amp;gt;length);&lt;br /&gt; NRFX_LOG_DEBUG(&amp;quot;Sequence data:&amp;quot;);&lt;br /&gt; NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_sequence-&amp;gt;values.p_raw,&lt;br /&gt; p_sequence-&amp;gt;length * sizeof(uint16_t));&lt;br /&gt; return start_playback(p_instance, p_cb, flags,&lt;br /&gt; odd ? NRF_PWM_TASK_SEQSTART1 : NRF_PWM_TASK_SEQSTART0);&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It looks to me like the if statement I have bolded is what you are referring to which is then used in the function call &lt;span&gt;nrf_pwm_shorts_set(p_instance-&amp;gt;p_registers, shorts_mask);&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Could you explain what this shorts_set is doing? Are you recommending that I simply pass in 0 to the nrfx_pwm_simple_playback() funcitonso that this shorts_mask gets set to 0? What are the second/third order effects from this change? I am unfamiliar with what exactly is happening with all of these calls as I took this from an example.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Something to note, today I switched from the stoppwm function call to fully uninitializing pwm each time and reinitializing it when I want to turn it back on. I have not seen the issue reappear since implementing this scheme but it has been only a half day or so of testing at this point. This is not ideal but it is potentially an acceptable workaround if nothing else works.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Thank you for your help,&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Austin&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Pwm Stays on even when proper stop functions are called</title><link>https://devzone.nordicsemi.com/thread/280723?ContentTypeID=1</link><pubDate>Wed, 18 Nov 2020 23:54:04 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9212f018-10dd-46bd-9191-8c262c53e533</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Not sure if this is your issue, but if only using 1 value there is an errata which may be applicable, not sue of the internal Nordic nRFx implementation, might be worth checking that:&lt;/p&gt;
&lt;h1 class="title topictitle1" id="ariaid-title1"&gt;[183] PWM: False SEQEND[0] and SEQEND[1] events&lt;/h1&gt;
&lt;div class="body refbody"&gt;
&lt;p class="shortdesc"&gt;This anomaly applies to IC Rev. Revision 2, build codes CKAA-Dx0, QIAA-Dx0.&lt;/p&gt;
&lt;div class="section"&gt;It was inherited from the previous IC revision&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a class="xref" href="https://infocenter.nordicsemi.com/topic/errata_nRF52840_EngD/ERR/nRF52840/EngineeringD/latest/err_840.html"&gt;Engineering D&lt;/a&gt;.&lt;/div&gt;
&lt;div class="section"&gt;
&lt;h2 class="title sectiontitle"&gt;Symptoms&lt;/h2&gt;
&lt;p class="p"&gt;False SEQEND[0] and SEQEND[1] events are being generated.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section"&gt;
&lt;h2 class="title sectiontitle"&gt;Conditions&lt;/h2&gt;
&lt;p class="p"&gt;Any of the LOOPSDONE_SEQSTARTn shortcuts are enabled. LOOP register is non-zero and sequence 1 is one value long.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section"&gt;
&lt;h2 class="title sectiontitle"&gt;Consequences&lt;/h2&gt;
&lt;p class="p"&gt;SEQEND[0] and SEQEND[1] events might falsely trigger other tasks if these are routed through the PPI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section"&gt;
&lt;h2 class="title sectiontitle"&gt;Workaround&lt;/h2&gt;
&lt;p class="p"&gt;Avoid using the LOOPSDONE_SEQSTARTn shortcuts, when LOOP register is non-zero and sequence 1 is one value long&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Pwm Stays on even when proper stop functions are called</title><link>https://devzone.nordicsemi.com/thread/280709?ContentTypeID=1</link><pubDate>Wed, 18 Nov 2020 21:41:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:09e652b8-e441-49db-b1ba-d5305b72b4d2</guid><dc:creator>Austin Fox</dc:creator><description>&lt;p&gt;Here is some more detailed code pieces&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;static DeviceState_t PwmState = Off;&lt;/p&gt;
&lt;p&gt;// This is for tracking PWM instances being used, so we can unintialize only&lt;br /&gt;// the relevant ones when switching from one demo to another.&lt;br /&gt;#define USED_PWM(idx) (1UL &amp;lt;&amp;lt; idx)&lt;br /&gt;static uint8_t m_used = 0;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;static uint16_t const m_demo1_top = 10000;&lt;br /&gt;static uint16_t const m_demo1_step = 200;&lt;br /&gt;static uint8_t m_demo1_phase;&lt;br /&gt;static nrf_pwm_values_individual_t m_demo1_seq_values;&lt;br /&gt;static nrf_pwm_sequence_t const m_demo1_seq =&lt;br /&gt;{&lt;br /&gt; .values.p_individual = &amp;amp;m_demo1_seq_values,&lt;br /&gt; .length = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values),&lt;br /&gt; .repeats = 0,&lt;br /&gt; .end_delay = 0&lt;br /&gt;};&lt;/p&gt;
&lt;p&gt;#define MAX_TOP 44 // Operating Frequency = 16MHz/(2*MAX_TOP)&lt;br /&gt;#define DEAD_BAND 2 // 8 is 1uSec dead band either side at Prescaler div 2 - base clock frequency /2 -&amp;gt;8MHz&lt;br /&gt;#define PHASE_HIGH (DEAD_BAND+(MAX_TOP/2))&lt;/p&gt;
&lt;p&gt;#define PWM_HIA_START 1&lt;br /&gt;#define PWM_LIA_START 3&lt;/p&gt;
&lt;p&gt;uint8_t PwmHiaDutyCycle = PWM_HIA_START; //This number must be manipulated as follows: PWM_LoopTable[0].channel_0 = 0x80000 | (PwmHiaDutyCycle);&lt;br /&gt;uint8_t PwmLiaDutyCycle = PWM_LIA_START; //This number is set directly as follows: PWM_LoopTable[0].channel_1 = PwmLiaDutyCycle;&lt;/p&gt;
&lt;p&gt;// This table is designed to use the Loops mode&lt;br /&gt;nrf_pwm_values_wave_form_t PWM_LoopTable[] = {&lt;br /&gt; // Index PWM-1 PWM-2 Other Top Value&lt;br /&gt; // ===== ====================== ============== =========== ============&lt;br /&gt; { /* - */ 0x8000 | (PWM_HIA_START), (PWM_LIA_START), (0), (MAX_TOP) }&lt;br /&gt;};&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;static nrfx_pwm_t myPWM = NRFX_PWM_INSTANCE(2);&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;#define PIN_PWM_HIA NRF_GPIO_PIN_MAP(0,26)&lt;br /&gt;#define PIN_PWM_LIA NRF_GPIO_PIN_MAP(0,27)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;void InitDualRampPWM(void)&lt;br /&gt;{&lt;br /&gt; uint32_t err_code;&lt;br /&gt; // Declare a configuration structure and use a macro to instantiate it with default parameters.&lt;br /&gt; nrfx_pwm_config_t pwm_config = NRFX_PWM_DEFAULT_CONFIG;&lt;br /&gt; // Configure PWM pins as outputs, and set to 0&lt;br /&gt; //nrf_gpio_cfg_output(PIN_PWM_HIA);&lt;br /&gt; //nrf_gpio_cfg_output(PIN_PWM_LIA);&lt;br /&gt; nrf_gpio_pin_clear(PIN_PWM_HIA);&lt;br /&gt; nrf_gpio_pin_clear(PIN_PWM_LIA);&lt;br /&gt; // Boost differential pwm driver pins to high drive if direct drive and not FET inputs&lt;br /&gt; nrf_gpio_cfg(PIN_PWM_HIA, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);&lt;br /&gt; nrf_gpio_cfg(PIN_PWM_LIA, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);&lt;br /&gt; // Override default PWM parameters:&lt;br /&gt; pwm_config.output_pins[0] = PIN_PWM_HIA;&lt;br /&gt; pwm_config.output_pins[1] = PIN_PWM_LIA;&lt;br /&gt; pwm_config.output_pins[2] = NRFX_PWM_PIN_NOT_USED;&lt;br /&gt; pwm_config.output_pins[3] = NRFX_PWM_PIN_NOT_USED;&lt;/p&gt;
&lt;p&gt;pwm_config.load_mode = NRF_PWM_LOAD_WAVE_FORM; // Mode of loading sequence data from RAM: 3 == Use individual duty cycle for each PWM channel&lt;br /&gt; pwm_config.base_clock = PWM_PRESCALER_PRESCALER_DIV_1; // Prescaler - Base clock frequenc: 4 == /16, so 1MHz&lt;br /&gt; pwm_config.count_mode = PWM_MODE_UPDOWN_UpAndDown; // Operating mode of the pulse generator counter&lt;br /&gt; pwm_config.irq_priority = 6; // Interrupt priority&lt;br /&gt; pwm_config.step_mode = 0; // Decoder - Mode of advancing the active sequence: 0 = Sequence&lt;br /&gt; pwm_config.top_value = 100; // 16-bit Value up to which the pulse generator counter counts: 3-32767, Not used in waveform mode&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;// Pass config structure into driver init() function&lt;br /&gt; err_code = nrfx_pwm_init(&amp;amp;myPWM, &amp;amp;pwm_config, NULL); // (nrfx_pwm_t p_instance, nrfx_pwm_config_t p_config, nrfx_pwm_handler_t handler)&lt;br /&gt; APP_ERROR_CHECK(err_code);&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;void UninitDualRampPWM(void){&lt;br /&gt; uint32_t err_code;&lt;br /&gt; nrfx_pwm_uninit(&amp;amp;myPWM); //(nrfx_pwm_t p_instance)&lt;br /&gt; PwmState = Off;&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;nrf_pwm_sequence_t const seq0 =&lt;br /&gt;{&lt;br /&gt; .values.p_wave_form = PWM_LoopTable,&lt;br /&gt; .length = NRF_PWM_VALUES_LENGTH(PWM_LoopTable),&lt;br /&gt; .repeats = 1,&lt;br /&gt; .end_delay = 0&lt;br /&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Bool StopPwm(void){&lt;br /&gt; GpioOutputMosfetDisable();&lt;br /&gt; nrfx_pwm_stop(&amp;amp;myPWM, 1);&lt;br /&gt; PwmState = Off;&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;bool CheckPwmStop(void){&lt;br /&gt; return nrfx_pwm_is_stopped(&amp;amp;myPWM);&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;void StartPwm(void){&lt;br /&gt; //Set Duty Cycle and Start PWM playback&lt;br /&gt; if(PwmHiaDutyCycle == 0){&lt;br /&gt; PwmHiaDutyCycle = MIN_HIA;&lt;br /&gt; PwmLiaDutyCycle = MIN_LIA;&lt;br /&gt; }&lt;br /&gt; else if(PwmHiaDutyCycle &amp;gt;MAX_HIA){&lt;br /&gt; PwmHiaDutyCycle = MAX_HIA;&lt;br /&gt; PwmLiaDutyCycle = MAX_LIA;&lt;br /&gt; }&lt;br /&gt; PWM_LoopTable[0].channel_0 = 0x8000 | PwmHiaDutyCycle;&lt;br /&gt; PWM_LoopTable[0].channel_1 = PwmLiaDutyCycle;&lt;br /&gt; (void)nrfx_pwm_simple_playback(&amp;amp;myPWM, &amp;amp;seq0, 1,NRFX_PWM_FLAG_LOOP); //TODO: Does this void parenthesis work well?&lt;br /&gt; //DataHubSetChargingStatus();//Charging Status should always be on any time StartPWM is called&lt;br /&gt; PwmState = True;&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>