Home
JAQForum Ver 19.10.27
Log In or Join  
Active Topics
Local Time 17:03 12 Dec 2019 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Critical Section in MMBasic

     Page 1 of 2    
Author Message
Bowden_P
Newbie

Joined: 20/03/2019
Location: United Kingdom
Posts: 14
Posted: 12:01am 19 Nov 2019
Copy link to clipboard 
Print this post

Hi everyone,
I am using an HX711 chip on a Mikroelektronika "Click" board to interface to a weigh scale load cell. I have a program which reads this chip successfully most of the time, but occasionally returns a completely wrong value. The Click board is plugged into a Micromite Plus Explore 100 board. My program generates a serial clock stream to transfer load cell data.

Edits to the program appear to change the frequency of this error. The HX711 chip relies on the serial clock PD_SCK pin not staying high too long - less than 60us - or it goes into standby. It requires a -ve edge on the clock to awake it, when it then goes to a default setting, which is not my programmed setting.

I am wondering if a Micromite Plus interrupt is occurring occasionally during the serial clocking sequence, so causing an inadvertent standby. Following re-reading may then return a high or corrupt value.

Is it possible to create a "critical section" in MMBasic so that clock sequences cannot be interrupted in this way?

With best regards, Paul.
 
KeepIS

Guru

Joined: 13/10/2014
Location: Australia
Posts: 527
Posted: 01:36am 19 Nov 2019
Copy link to clipboard 
Print this post

I found the Touch interrupts can cause this and cause random stretching of the clock transitions.

In the end I set a flag in the Touch up/dn ISR and simply dropped the data packet if the flag was set as I exited the clock / read cycle. Completely stopped the problem.

Mike.

EDIT: I forgot to add that any interrupts I defined also needed to set the flag to abort the current read cycle.
Edited 2019-11-19 12:05 by KeepIS
It's all too hard.
 
panky

Guru

Joined: 02/10/2012
Location: Australia
Posts: 669
Posted: 03:29am 19 Nov 2019
Copy link to clipboard 
Print this post

Paul,

Your requirements sound like a perfect example where a CFunction would do the trick.

A CFunction is some code written in C that gets embedded into the MMBasic interpreter essentially as extensions to MMBasic.  The CFunction has the highest interrupt level thus when called from MMBasic, will not be affected by any lower order interrupts.

Given the need to generate 25 to 27 narrow pulses somewhere between 0.2uS and 50uS then read the data line > 0.2uS after the rising edge of each clock pulse, a CFunction could generate all the clock signals and read the data generated into an array.

Sadly, creating such a CFunction is beyond my capabilities but if you are game to have a go at some C programming, there are several posts on CFunctions on the forum that may assist you.

panky

PS. The MMbasic 2 Manual has info on the interrupt order around page 40.
Edited 2019-11-19 13:30 by panky
... all the Maximites, almost all of the MicromMites, all the MM Extremes, all the ArmMites, and loving it!
 
panky

Guru

Joined: 02/10/2012
Location: Australia
Posts: 669
Posted: 03:34am 19 Nov 2019
Copy link to clipboard 
Print this post

This post, Oneshot CFunctions has some helpful info on CFunctions and pulses.

panky
... all the Maximites, almost all of the MicromMites, all the MM Extremes, all the ArmMites, and loving it!
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 3136
Posted: 04:55am 19 Nov 2019
Copy link to clipboard 
Print this post

How are you generating the clock pulses?
I would think that:

for n = 1 to 24
PULSE CLK_PIN, 0.05
databit(n) = PIN(DATA_PIN)
next n

would have the high pulse length safe from interrupts.
The low time doesn't seem to be a problem although there probably is some maximum time to stay within.

Jim
It all started with the ZX81....
VK7JH
http://www.c-com.com.au/MMedit.htm
 
KeepIS

Guru

Joined: 13/10/2014
Location: Australia
Posts: 527
Posted: 05:35am 19 Nov 2019
Copy link to clipboard 
Print this post

Hi Jim, I had a similar problem with a clocked device seeing a slight extension of the low pulse as a request for a start of packet.

On a H7 @ 480MHz any touch or defined interrupt trigger would cause a reading error about 1 in 10 to 15 times, which was a critical error that I had to detect and halt the machinery on. I couldn't use C-functions on the H7.

BTW On a previous thread we found that using an assigned name for the PIN made a huge difference to the loop and transition speeds, I think you were in on that thread, so I was forced to use the actual PIN numbers.

Interestingly (IN MY CASE) the PULSE command was not as good as PIN HI/LO control, but I was using the loop read time to my advantage and changing the HI/LO transitions around the Data bit read, I attained very high pulse rates with no glitches or misreads under any circumstance, in fact the H7 and modified clock/RX code left the supplied OEM read heads for dead in every way.


Mike.
It's all too hard.
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 2570
Posted: 08:11am 19 Nov 2019
Copy link to clipboard 
Print this post

It would be interesting to see how you are generating the clock stream.  While MMBasic is fast (for an interpreter) a pulse width <60uS would very difficult to generate using BASIC commands.

Could you generate the clock pulse using a PWM output or SPI channel?

Geoff
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 995
Posted: 09:37am 19 Nov 2019
Copy link to clipboard 
Print this post

  panky said  
Sadly, creating such a CFunction is beyond... <snip>


and not (yet?) possible on the bigger beasts. So if you are looking at anything other than a stock MM this is a no-go
Edited 2019-11-19 19:38 by CaptainBoing
 
Bowden_P
Newbie

Joined: 20/03/2019
Location: United Kingdom
Posts: 14
Posted: 05:59pm 19 Nov 2019
Copy link to clipboard 
Print this post

Hi everyone,
Many thanks for your replies. While there is a max. time limit on the clock pin "PD_SCK" being high, there appears no max. limit when it is low.

GeoffG :-
--------
To generate the clock pulse I am using a basic(!) sequence :-
Pin(PD_SCK)=1
Pin(PD_SCK)=0

I timed this on a 'scope, which showed the Pin() instruction took 26us. to execute with a 100MHz system clock, although there was also about +8us. jitter evident. ( Well within the HX711 spec. of <60us.)

Following every PD_SCK pulse the data output DOUT needs checking, to construct the 24 bit load cell output.
From my program :-

Sub Get_a_Measure
 ' Fetches a measurement from the Load Cell Click board.
 ' The measured value is passed back in the global "Data_24%".
 local gam_count%,gam_d_level%,gam_bit%
 
 Data_24%=0
 For gam_count%=23 To 0 Step -1  ' Read 24 bits of data from DOUT,
   Pin(PD_SCK%)=1                ' m.s.b. first.
   Pin(PD_SCK%)=0
   gam_d_level%=Pin(D_OUT%)
   gam_bit%=2^gam_count%
   
   If gam_d_level%=1 Then
     Data_24%=Data_24% OR gam_bit% ' Construct the Data word.
   EndIf
   
 Next gam_count%
 
 Pin(PD_SCK%)=1              ' Clock 3 more times for Channel A, x64 Gain,
 Pin(PD_SCK%)=0              ' on the NEXT measurement.
 
 Pin(PD_SCK%)=1
 Pin(PD_SCK%)=0
 
 Pin(PD_SCK%)=1
 Pin(PD_SCK%)=0
End Sub


While using PWM would seem a bit tricky timing-wise, your SPI idea is interesting, and would ease the re-construction of the 24-bit data. ( SPI in Mode 1, using a bulk READ perhaps?)

KeepIS :-
--------
Thanks for your experience and cure using a flag. I am using a SETTICK interrupt to time when to read the HX711, so would need to re-structure the program to use this idea! However, any idea is worth thinking about.

panky :-
-------
CFunctions - Hmm! Like you, I don't "speak" C, although I have toyed with the idea of learning it some time.

Would a CFunction actually completely suspend any other interrupts running, so guaranteeing defined timings?

Thanks for the link.

TassyJim :-
----------
I can't see any max. to the clock low time in the datasheet. Your code is a deal tidier than mine - I'll give it a try.

With best regards, Paul.
 
Tinine
Senior Member

Joined: 30/03/2016
Location: United Kingdom
Posts: 268
Posted: 07:07pm 19 Nov 2019
Copy link to clipboard 
Print this post

PMJI

According to the doc's, the SETTICK is a low priority interrupt? I don't have the doc's in front of me.

I recently suggested launching a PWM and have it wired back to a input interrupt.

Would this be a higher priority?

Regards,

Craig
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 3136
Posted: 07:58pm 19 Nov 2019
Copy link to clipboard 
Print this post

With your code, it is possible that an interrupt took over between setting the pin high and bringing it low again.

I would simply replace

Pin(PD_SCK)=1
Pin(PD_SCK)=0

with

PULSE PD_SCK, 0.01

which would give a reliable 10uS high pulse
The rest of the code could stay the same

Jim
Edited 2019-11-20 06:00 by TassyJim
It all started with the ZX81....
VK7JH
http://www.c-com.com.au/MMedit.htm
 
Bowden_P
Newbie

Joined: 20/03/2019
Location: United Kingdom
Posts: 14
Posted: 11:01pm 19 Nov 2019
Copy link to clipboard 
Print this post

Hi Tinine and TassyJim,
Thanks for your replies.

TassyJim :-
----------
Your mod to use "PULSE PD_SCK,0.01" works very well!! Thanks for the suggestion. I have been watching the display for some 20 minutes without wrong values at all. Previously 1 or 2 duff values would register roughly every 2 minutes. Looks definitely like the suspicion of other interrupts cutting in was the correct one.

Tinine :-
--------
You're right about the SETTICK priority - it is at the "bottom of the heap" with priority 14, with an I/O interrupt just ahead at 13! ( For MM+.)

GeoffG :-
--------
Using an SPI interface looked a useful idea to implement, but then I am restricted to the Load Cell Click board defining the channels I must use for its clock and data channels - 82 and 8 respectively - not the ClickBus standard at all! Possibly the software CFunction SPI would work - I will look at that.

One thing I am wondering - does MMBasic - or the 32MX470 micro - allow higher priority interrupts to interrupt lower priority interrupts while they are running? Useful to know for background info.

Many thanks to all contributors,
With best regards, Paul.
 
KeepIS

Guru

Joined: 13/10/2014
Location: Australia
Posts: 527
Posted: 11:14pm 19 Nov 2019
Copy link to clipboard 
Print this post

I'm hope I'm not hijacking the OP's thread here, but just an FYI as to why I didn't use the PULSE command, or gave up on other suggested options.

The problem I had with using PULSE for a clock is when the data has to be read while the clock transition is still HIGH. If a pulse is used, I have around 40 micro seconds to grab a data bit and get the clock high again, any longer and the Device resets the 24 Bit stream to the start of the stream, regardless of the clock cycle count.          

In other words, the Data line state is read between the clock transition pulse for a series of 24 clock cycles and, the data read can be either a positive or negative value and that status sign bit is the LAST bit clocked out.

I spent hours timing a small clock / data loop in conjunction with having to assemble the value returned in, and outside the loop, and having to reverse the number for two's complement on a fast moving transition from POS to NEG outside the clock data loop.  

In the end it was faster to actually treat the data bit stream as both pos and neg and assemble it accordingly inside the clock loop, the select which one to use on the last bit status.

This sounds counter intuitive and wasteful, but the result was 5.6 Ms total read and assemble time, with a variation of 0.03 Ms, allowing me to clock and read 3 input devices, average them and maintain virtually instantaneous Stepper motor Hardware response to input changes.

You can see why I had to trap Touch (ON KEY) as it's the highest priority INT behind a C-FUN.  

Apology for long post, hope it makes some sense?

Mike
It's all too hard.
 
Bowden_P
Newbie

Joined: 20/03/2019
Location: United Kingdom
Posts: 14
Posted: 11:41pm 19 Nov 2019
Copy link to clipboard 
Print this post

Hi KeepIS,
Looks like your problem was more awkward than mine - with such a narrow window to snatch the data. For the HX711 all it needs is a clock high time less than the critical 60us maximum. The data remains stable until the next +ve-going edge.
Thanks for your interest, Paul.
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 2570
Posted: 05:15am 20 Nov 2019
Copy link to clipboard 
Print this post

  Bowden_P said  One thing I am wondering - does MMBasic - or the 32MX470 micro - allow higher priority interrupts to interrupt lower priority interrupts while they are running? Useful to know for background info.

The short answer is no.

In MMBasic interrupts are handled by the interpreter at the end of each command - they are not hardware (ie, PIC32MX470) interrupts.  Due to the way BASIC works it is difficult to implement nested interrupts and in the interest of fitting the interpreter into the limited flash memory of a microcontroller this was a feature that did not make it into the final cut.

Normally interrupts in MMBasic do something simple (like set a flag) then exit.  This technique largely removes the need for nested interrupts.
 
Bowden_P
Newbie

Joined: 20/03/2019
Location: United Kingdom
Posts: 14
Posted: 02:16pm 20 Nov 2019
Copy link to clipboard 
Print this post

Hi Geoffg,
Thanks for clarifying no nesting, also when the interrupts are handled - at the end of a command. My earlier experience for PIC micros is in the smaller 12F to 16F devices and assembly language, where instructions are "atomic" too.
With thanks, Paul.
 
nasi
Newbie

Joined: 08/07/2015
Location: Australia
Posts: 15
Posted: 04:44pm 20 Nov 2019
Copy link to clipboard 
Print this post

  Geoffg said  It would be interesting to see how you are generating the clock stream.  While MMBasic is fast (for an interpreter) a pulse width <60uS would very difficult to generate using BASIC commands.

Could you generate the clock pulse using a PWM output or SPI channel?

Geoff


I do love the maximite but mine has been collecting dust for a while for that reason.

SBC Raspi is just making my life too easy.
Sorry Geoff
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 2973
Posted: 05:00pm 20 Nov 2019
Copy link to clipboard 
Print this post

These CFunctions stop and start the RTC in the MM. Stop the clock before sending your short pulse and start it again afterwards then it should always be the same length. The 1mSec clock is the only hardware interrupt running

CSUB stopclock
00000000
3c030008 3c02bf88 ac431064 3c02bf88 ac401068 03e00008 00000000
End CSUB
CSUB startclock
00000000
3c020008 3c03bf88 ac621064 3c03bf88 ac621068 03e00008 00000000
End CSUB

Edited 2019-11-22 01:44 by matherp
 
Bowden_P
Newbie

Joined: 20/03/2019
Location: United Kingdom
Posts: 14
Posted: 11:30pm 21 Nov 2019
Copy link to clipboard 
Print this post

Hi matherp,
Many thanks for the 2 CFunction subs. That's very interesting to know about how the MM clock is serviced in MMBasic. I will try these in the relevant subroutines. I have seen rhythmic variations in timings, so it will be interesting if they stop with no MM clock.

I measured the period of last 3 pulses, now made with "PULSE PD_SCK,0.01" instructions - 40us approx., so an instruction overhead of about 30us. (MM+ Explore 100 with a 100MHz clock.)

It will be about a week before I can check the stopped clock effects - sorry about this delay.

With best wishes, Paul.
 
Bowden_P
Newbie

Joined: 20/03/2019
Location: United Kingdom
Posts: 14
Posted: 09:45pm 26 Nov 2019
Copy link to clipboard 
Print this post

Hi Peter,
I have tried the CSUB's and they stop my program! I do have a time display (HH:MM) running using TIME$, a SETTICK to time its update and flash the colon, and elsewhere several PAUSE commands. Do these rely on the MM clock running?

Oddly, the CSUB call requires "stopclock" plus brackets - "stopclock()". If no brackets - Syntax error results.

A CTRL C gets back to the command level, but the cursor has stopped flashing! Not quite the effect anticipated I guess. A "startclock()" restarts the cursor.

With regards, Paul.
 
     Page 1 of 2    
Print this page
© JAQ Software 2019