EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

How to best handle multiple interrupts

Started by Yuriy's Toys February 14, 2013
Hello,
Could someone enlighten me on what's the bes approach to doing the following is:

I need to read a set of three "Chinese calipers" connected to one of the "cheap" MSP430s (probably MSP430G2153). The calipers use a synchronous serial protocol. (On one line they provide the clock signal, and on the other - data). Once the position is read, it needs to be sent over UART to the mothership.
Reading one caliper is easy: I would set an interrupt on the raising edge and read the data pin in the ISR. Here is what gets me with 3 calipers:
1. I need to have a timeout timer on each line to detect the period between "data streams", and if the timer overflows, reset the state machine.
2. I need to have three interrupts.
3. When the state machine accepts the position, I need to send it over UART.

The question is: what is the proper way to handle all this. It looks like I will have an interrupt bonanza. If I disable the interrupts while sending the data over the slow UART, the position will miss. Same inside each position. I'd like to stick with a Launchpad part, since this is an open source "community" project, and most target users have limited experience with electronics. The only way I know how to deal with this is with an ARM MCU that supports nested interrupts and (preferably) "round robin" interrupt scheduling. Can this be done well with a "small" MSP430? If yes, I would really appreciate some guidance.

Thank you in advance
Yuriy

More details on the protocol can be found here: http://www.shumatech.com/support/chinese_scales.htm

I'm trying to do this (different scales, same setup):
http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html

Beginning Microcontrollers with the MSP430

You can definitely do nested interrupts with the 430. Sadly I can't tell you anything about whether Launchpad parts do or don't allow nested interrupts. I often need to interrupt UART or SPI transfers with high rate interrupts.

It sounds like you need a packet queue in your main thread/loop for your UART data.
By default I think interrupts are disabled in the interrupt handler, however you can reenable interrupts such that an interrupt can be interrupted. I don't know what the maximum message from the device is but lets say it 20 bytes. Create an array of max packets x 20 bytes. When any interrupt sequence starts, increment the queue so the next interrupt will write into the next slot. Thus 3 (or more) 'packets' could be constructed simultaneously. When it's complete set a flag for that entry in the list to be flushed, your main should be looping looking for any set flag, and if it finds one, clears it and sends that down the UART. You could space out the rate at which you send the UART bytes to give the other interrupts more chance, however if a pin interrupt happens will dealing with a UART interrupt (or any other interrupt for that matter) it just gets queued and handled after. The UART TX wouldn't be an issue anyway, just a lengthy UART RX handler might cause you grief, but you could reenable interrupts in that handler if it was problematic.

cheers,
Phil

--- In m..., "Yuriy's Toys" wrote:
>
> Hello,
> Could someone enlighten me on what's the bes approach to doing the following is:
>
> I need to read a set of three "Chinese calipers" connected to one of the "cheap" MSP430s (probably MSP430G2153). The calipers use a synchronous serial protocol. (On one line they provide the clock signal, and on the other - data). Once the position is read, it needs to be sent over UART to the mothership.
> Reading one caliper is easy: I would set an interrupt on the raising edge and read the data pin in the ISR. Here is what gets me with 3 calipers:
> 1. I need to have a timeout timer on each line to detect the period between "data streams", and if the timer overflows, reset the state machine.
> 2. I need to have three interrupts.
> 3. When the state machine accepts the position, I need to send it over UART.
>
> The question is: what is the proper way to handle all this. It looks like I will have an interrupt bonanza. If I disable the interrupts while sending the data over the slow UART, the position will miss. Same inside each position. I'd like to stick with a Launchpad part, since this is an open source "community" project, and most target users have limited experience with electronics. The only way I know how to deal with this is with an ARM MCU that supports nested interrupts and (preferably) "round robin" interrupt scheduling. Can this be done well with a "small" MSP430? If yes, I would really appreciate some guidance.
>
> Thank you in advance
> Yuriy
>
> More details on the protocol can be found here: http://www.shumatech.com/support/chinese_scales.htm
>
> I'm trying to do this (different scales, same setup):
> http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html
>

Why not let the msp handle the serial data for you? You have clock and data so you should be able to treat the caliper as a spi master and the msp as a slave. You then only need to interrupt after every byte of data or, if you use DMA, after every word or series of words.
Then a consumer task can wake up and process the sample(s). Another task can check the state, etc.

--- In m..., "Yuriy's Toys" wrote:
>
> Hello,
> Could someone enlighten me on what's the bes approach to doing the following is:
>
> I need to read a set of three "Chinese calipers" connected to one of the "cheap" MSP430s (probably MSP430G2153). The calipers use a synchronous serial protocol. (On one line they provide the clock signal, and on the other - data). Once the position is read, it needs to be sent over UART to the mothership.
> Reading one caliper is easy: I would set an interrupt on the raising edge and read the data pin in the ISR. Here is what gets me with 3 calipers:
> 1. I need to have a timeout timer on each line to detect the period between "data streams", and if the timer overflows, reset the state machine.
> 2. I need to have three interrupts.
> 3. When the state machine accepts the position, I need to send it over UART.
>
> The question is: what is the proper way to handle all this. It looks like I will have an interrupt bonanza. If I disable the interrupts while sending the data over the slow UART, the position will miss. Same inside each position. I'd like to stick with a Launchpad part, since this is an open source "community" project, and most target users have limited experience with electronics. The only way I know how to deal with this is with an ARM MCU that supports nested interrupts and (preferably) "round robin" interrupt scheduling. Can this be done well with a "small" MSP430? If yes, I would really appreciate some guidance.
>
> Thank you in advance
> Yuriy
>
> More details on the protocol can be found here: http://www.shumatech.com/support/chinese_scales.htm
>
> I'm trying to do this (different scales, same setup):
> http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html
>

I'm not in a position to chasing your web links, so first of all the
launchpads I have came with the MSP430G2553. this only differs from the
2153 in the amount of Flash and RAM. The 2553 has 16K and 512bytes
respectively, while the 2153 has just 1K and 256 bytes. The amountof
available I/O resources will depend on the package, again mine came with
the 20pin version, so least resources.

However there should still be plenty. First comment would be that 1K may
not be enough memory, especially if you're writing in C,a nd the costy
of the Launchpads doesn't vary, so develop on the 2553 and then move
downwrd once you know how much memory you actually need. There are 14
pin based inetrrupts available and 6 timer channels/interrupts, so you
have plenty of resources. You even have a hardware UART.

Unfortunately the G series has only one pre-calibrated DCO speed, which
is 1MHz, I don't know if you can get variants on this, but this limits
your maximum UART speed. You haven't said what the clock speed of the
data from the scales is, nor what data rate you need from the UART, nor
whether you need to run at low power.

OK, managed to get the site on my phone, so 90kHz, nominal, but large
range, and 48 bit result sent every 300msecs, so 6 bytes per unit or
~18bytes of data per second. So low baud rate should be fine

You have 2 x 3 channel timers, so allocate 1 timer channel for each scale.

For simplicity and speed I would use registers to collect the data, so 3
registers per scale, that won't be a problem in assembler, but could be
in C.

The objective with interrupts is to keep them absolutely as short as
possible. Secondly you must try to ensure that all interrupts can be
processed within the minimum time between recurring interrupts to avoid
losing one. In your case, and given the apparent variance in data
clocks, assume a high end (worst case) of 125kHz data clock, then you
have an interrupt every 8usecs. Clearly a 1MHz clock isn't going to cut
it, so first of all work out how long you aare going to need to process
each interrupt. What do you need to do?

basically I figure that you need to either decide which of the 3
registers to collect the data in, or simply roll them through as a 48
bit register. the latter is faster. Also your foreground program will
need to do some management, for example once the 48 bits have been
collected it needs to zero counters and registers, so, the implication
is that we need a 4th register per scale to count bits. In addition we
need to know which pin interrupted. So here is what the ISR might look
like:_

P1_ISR:
AND.B #1,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
ON p1.0-2
JZ TSTSCALE2 ;NOT SET SO SKIP
BIT.B #1,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
RLC REG4 ;WHICH SAVES A FEW CLOCK CYCLES
RLC REG5
RLC REG6
DEC REG7 ;CONTINUE TO TEST NEXT SCALE IN CASE IT
HAS INTERRUPTED WHILE DOING SCALE 1
TSTSCALE2:
AND.B #2,&P1IFG ;
JZ TSTSCALE3
BIT.B #2,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
RLC REG8
RLC REG9
RLC REG10
DEC REG11
TSTSCALE3:
AND.B #4,&P1IFG ;
JZ ENDISR
BIT.B #4,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
RLC REG12
RLC REG13
RLC REG14
DEC REG15
ENDISR:
CLR.B &P1IFG
RETI

Each section from AND TO DEC takes 14 clock cycles, PLUS 5 FOR THE plus
latency on entry of up to 6 clock cycles and RETI of 5, plus you may
need to exit from LPM when exiting the ISR (BIC #LPM3,0(SP)) which would
add another 5 clock cycles, so this routine, which allows you to catch
all 3 interrupt sources in one pass takes up to 58 clock cycles no LPM
and 63 clock cycles in LPM IF ALL 3 SOURCES HAVE INTERRUPTED, else the
worst case for a single interrupt is SCALE3 which takes 36 CLOCK CYCLES.
Given the possibility of an 8usecond clock interrupt rate I would
suggest running the DCO at 16MHz, so that you had 128 clock cycles
between ASSUMED WORST CASE INTERRUPTS.

Obviousdly you could handle each ISR individually, but that adds time to
the overall processing requirement. It would look something like this:_

P1_ISR:
AND.B #1,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
ON p1.0-2
JNZ SCALE1 ;IS SET SO DO SCALE1
AND.B #2,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
ON p1.0-2
JNZ SCALE2 ;IS SET SO DO SCALE1
AND.B #4,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
ON p1.0-2
JNZ SCALE3 ;IS SET SO DO SCALE1
CLR.B &P1IFG
RETI

SCALE1:
BIT.B #1,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
RLC REG4 ;WHICH SAVES A FEW CLOCK CYCLES
RLC REG5
RLC REG6
DEC REG7 ;CONTINUE TO TEST NEXT SCALE IN CASE IT
HAS INTERRUPTED WHILE DOING SCALE 1
BIC.B #1,&P1IFG
RETI

ETC..ETC

This would make each individual interrupt take less time, but again
scale3 would take longer than the other 2 and the cumulative time for 3
interruptsd is longer.

On timers, simply use the timer compare function, when it interrupts,
use the foreground routine to detect it and do whatever you need to do.

This is quite simplistic,a nd your code will need to be quite efficient
to handle 3 scales. i haven't even looked at the overhead for the UART,
but that may not be possible within the remaining 65 clock cycles. A
stripped down but full function UART ISR, given that all the registers
have been eaten, will take around 38 clock cycles with LPM exit, latency
and end of packet detection. The danger then becomes the inability of
your foreground routine to process itself in the 27 remaining clock
cycles before the 48 bits have been collected. ie most of the foreground
will be running a test process until either a timer expires to cancel a
transaction or 48 bits have been collected and either a packet has to be
sent, , so it isn't as dire as it sounds, mostly your foreground will be
doing nothing but testing. For example a simple exampel might be:_

MAINLOOP:
TST R7 ;DO WE HAVE 48 BITS IN SCALE1
JZ STORESCALE1
TST R11
JZ STORESCALE2
TST R15
JZ STORESCALE3
TST TFLAGS ;1 BIT FLAGS TO INDICATE TIMER OVERFLOW
IN A SINGLE WORD/BYTE
JNZ DO_TIMERS ;HANDLE ANY TIMER OVERFLOW HERE
JMP MAINLOOP

STORESCALE1:
ETC

The UART doesn't necessarily need to be checked fro packet sent, but if
it does I generally disable the RX interrupt on end of packet, and that
could be used at the end of the MAINLOOP loop to detect and act on UART
data sent.

This is obviously a very stripped down example, and I obviously haven't
debugged it, but with a little padding, like init codes and the routines
to handle and manage data transmission, I don't see why it wouldn't
work, although I would not bother trying to catch every single packet
from the scale, i would simply collect a set of data, and then stall
that scale until I was ready again.

Hope that helps

Al

On 14/02/2013 6:18 PM, Yuriy's Toys wrote:
> Hello,
> Could someone enlighten me on what's the best approach to doing the following is:
>
> I need to read a set of three "Chinese calipers" connected to one of the "cheap" MSP430s (probably MSP430G2153). The calipers use a synchronous serial protocol. (On one line they provide the clock signal, and on the other - data). Once the position is read, it needs to be sent over UART to the mothership.
> Reading one caliper is easy: I would set an interrupt on the raising edge and read the data pin in the ISR. Here is what gets me with 3 calipers:
> 1. I need to have a timeout timer on each line to detect the period between "data streams", and if the timer overflows, reset the state machine.
> 2. I need to have three interrupts.
> 3. When the state machine accepts the position, I need to send it over UART.
>
> The question is: what is the proper way to handle all this. It looks like I will have an interrupt bonanza. If I disable the interrupts while sending the data over the slow UART, the position will miss. Same inside each position. I'd like to stick with a Launchpad part, since this is an open source "community" project, and most target users have limited experience with electronics. The only way I know how to deal with this is with an ARM MCU that supports nested interrupts and (preferably) "round robin" interrupt scheduling. Can this be done well with a "small" MSP430? If yes, I would really appreciate some guidance.
>
> Thank you in advance
> Yuriy
>
> More details on the protocol can be found here: http://www.shumatech.com/support/chinese_scales.htm
>
> I'm trying to do this (different scales, same setup):
> http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html
>
>
I would recommend learning the DMA, becuase the process it will take you
to get it working will give you such an insight into how SPI should work.

On 2/14/2013 8:01 AM, raffuj wrote:
> Why not let the msp handle the serial data for you? You have clock and
> data so you should be able to treat the caliper as a spi master and
> the msp as a slave. You then only need to interrupt after every byte
> of data or, if you use DMA, after every word or series of words.
> Then a consumer task can wake up and process the sample(s). Another
> task can check the state, etc.
>
> --- In m... ,
> "Yuriy's Toys" wrote:
> >
> > Hello,
> > Could someone enlighten me on what's the bes approach to doing the
> following is:
> >
> > I need to read a set of three "Chinese calipers" connected to one of
> the "cheap" MSP430s (probably MSP430G2153). The calipers use a
> synchronous serial protocol. (On one line they provide the clock
> signal, and on the other - data). Once the position is read, it needs
> to be sent over UART to the mothership.
> > Reading one caliper is easy: I would set an interrupt on the raising
> edge and read the data pin in the ISR. Here is what gets me with 3
> calipers:
> > 1. I need to have a timeout timer on each line to detect the period
> between "data streams", and if the timer overflows, reset the state
> machine.
> > 2. I need to have three interrupts.
> > 3. When the state machine accepts the position, I need to send it
> over UART.
> >
> > The question is: what is the proper way to handle all this. It looks
> like I will have an interrupt bonanza. If I disable the interrupts
> while sending the data over the slow UART, the position will miss.
> Same inside each position. I'd like to stick with a Launchpad part,
> since this is an open source "community" project, and most target
> users have limited experience with electronics. The only way I know
> how to deal with this is with an ARM MCU that supports nested
> interrupts and (preferably) "round robin" interrupt scheduling. Can
> this be done well with a "small" MSP430? If yes, I would really
> appreciate some guidance.
> >
> > Thank you in advance
> > Yuriy
> >
> > More details on the protocol can be found here:
> http://www.shumatech.com/support/chinese_scales.htm
> >
> > I'm trying to do this (different scales, same setup):
> >
> http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html
> >



On Thu, Feb 14, 2013 at 11:12 AM, Onestone wrote:

> Unfortunately the G series has only one pre-calibrated DCO speed, which
> is 1MHz,

This is correct only for the first generation G2 series parts. The
2533 (third generation G2) has factory calibration data for 1, 8, 12,
and 16 MHz. I am not sure offhand about the second generation G2
parts offhand.

> The objective with interrupts is to keep them absolutely as short as
> possible. Secondly you must try to ensure that all interrupts can be
> processed within the minimum time between recurring interrupts to avoid
> losing one.

My understanding is that the MSP430 queues single pending interrupts.
If you get an interrupt condition while interrupts are disabled (as in
an ISR) that interrupt will get triggered when interrupts are
re-enabled. This will lead to jitter, but at least you won't lose the
interrupt. The only time you lose an interrupt is if you get a
*second* interrupt condition before you clear the interrupt flag from
the first one.

-p.
Correct on the interrupts. And thanks for the tip on the newer G2 parts.
I must admit I have only tinkered with my Launchpad, which is an old
one, and haven't used the G series in any other designs yet, so wasn't
aware of that.

Another implication, not to be ignored, is that the data pin must be
guaranteed to hold it's desired state long enough to guarantee being
read by the ISR before the next clock cycle.

Al

On 15/02/2013 4:09 AM, Peter Johansson wrote:
> On Thu, Feb 14, 2013 at 11:12 AM, Onestone wrote:
>
>> Unfortunately the G series has only one pre-calibrated DCO speed, which
>> is 1MHz,
> This is correct only for the first generation G2 series parts. The
> 2533 (third generation G2) has factory calibration data for 1, 8, 12,
> and 16 MHz. I am not sure offhand about the second generation G2
> parts offhand.
>
>> The objective with interrupts is to keep them absolutely as short as
>> possible. Secondly you must try to ensure that all interrupts can be
>> processed within the minimum time between recurring interrupts to avoid
>> losing one.
> My understanding is that the MSP430 queues single pending interrupts.
> If you get an interrupt condition while interrupts are disabled (as in
> an ISR) that interrupt will get triggered when interrupts are
> re-enabled. This will lead to jitter, but at least you won't lose the
> interrupt. The only time you lose an interrupt is if you get a
> *second* interrupt condition before you clear the interrupt flag from
> the first one.
>
> -p.
>
Al,
Thank you very much for a detailed write-up. This gives me a good starting point.

Thank you much
Yuriy
--- In m..., Onestone wrote:
>
> I'm not in a position to chasing your web links, so first of all the
> launchpads I have came with the MSP430G2553. this only differs from the
> 2153 in the amount of Flash and RAM. The 2553 has 16K and 512bytes
> respectively, while the 2153 has just 1K and 256 bytes. The amountof
> available I/O resources will depend on the package, again mine came with
> the 20pin version, so least resources.
>
> However there should still be plenty. First comment would be that 1K may
> not be enough memory, especially if you're writing in C,a nd the costy
> of the Launchpads doesn't vary, so develop on the 2553 and then move
> downwrd once you know how much memory you actually need. There are 14
> pin based inetrrupts available and 6 timer channels/interrupts, so you
> have plenty of resources. You even have a hardware UART.
>
> Unfortunately the G series has only one pre-calibrated DCO speed, which
> is 1MHz, I don't know if you can get variants on this, but this limits
> your maximum UART speed. You haven't said what the clock speed of the
> data from the scales is, nor what data rate you need from the UART, nor
> whether you need to run at low power.
>
> OK, managed to get the site on my phone, so 90kHz, nominal, but large
> range, and 48 bit result sent every 300msecs, so 6 bytes per unit or
> ~18bytes of data per second. So low baud rate should be fine
>
> You have 2 x 3 channel timers, so allocate 1 timer channel for each scale.
>
> For simplicity and speed I would use registers to collect the data, so 3
> registers per scale, that won't be a problem in assembler, but could be
> in C.
>
> The objective with interrupts is to keep them absolutely as short as
> possible. Secondly you must try to ensure that all interrupts can be
> processed within the minimum time between recurring interrupts to avoid
> losing one. In your case, and given the apparent variance in data
> clocks, assume a high end (worst case) of 125kHz data clock, then you
> have an interrupt every 8usecs. Clearly a 1MHz clock isn't going to cut
> it, so first of all work out how long you aare going to need to process
> each interrupt. What do you need to do?
>
> basically I figure that you need to either decide which of the 3
> registers to collect the data in, or simply roll them through as a 48
> bit register. the latter is faster. Also your foreground program will
> need to do some management, for example once the 48 bits have been
> collected it needs to zero counters and registers, so, the implication
> is that we need a 4th register per scale to count bits. In addition we
> need to know which pin interrupted. So here is what the ISR might look
> like:_
>
> P1_ISR:
> AND.B #1,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
> ON p1.0-2
> JZ TSTSCALE2 ;NOT SET SO SKIP
> BIT.B #1,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
> ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
> RLC REG4 ;WHICH SAVES A FEW CLOCK CYCLES
> RLC REG5
> RLC REG6
> DEC REG7 ;CONTINUE TO TEST NEXT SCALE IN CASE IT
> HAS INTERRUPTED WHILE DOING SCALE 1
> TSTSCALE2:
> AND.B #2,&P1IFG ;
> JZ TSTSCALE3
> BIT.B #2,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
> ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
> RLC REG8
> RLC REG9
> RLC REG10
> DEC REG11
> TSTSCALE3:
> AND.B #4,&P1IFG ;
> JZ ENDISR
> BIT.B #4,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
> ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
> RLC REG12
> RLC REG13
> RLC REG14
> DEC REG15
> ENDISR:
> CLR.B &P1IFG
> RETI
>
> Each section from AND TO DEC takes 14 clock cycles, PLUS 5 FOR THE plus
> latency on entry of up to 6 clock cycles and RETI of 5, plus you may
> need to exit from LPM when exiting the ISR (BIC #LPM3,0(SP)) which would
> add another 5 clock cycles, so this routine, which allows you to catch
> all 3 interrupt sources in one pass takes up to 58 clock cycles no LPM
> and 63 clock cycles in LPM IF ALL 3 SOURCES HAVE INTERRUPTED, else the
> worst case for a single interrupt is SCALE3 which takes 36 CLOCK CYCLES.
> Given the possibility of an 8usecond clock interrupt rate I would
> suggest running the DCO at 16MHz, so that you had 128 clock cycles
> between ASSUMED WORST CASE INTERRUPTS.
>
> Obviousdly you could handle each ISR individually, but that adds time to
> the overall processing requirement. It would look something like this:_
>
> P1_ISR:
> AND.B #1,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
> ON p1.0-2
> JNZ SCALE1 ;IS SET SO DO SCALE1
> AND.B #2,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
> ON p1.0-2
> JNZ SCALE2 ;IS SET SO DO SCALE1
> AND.B #4,&P1IFG ;TEST BIT0 OF IFG REGISTER, HAVE CLOCKS
> ON p1.0-2
> JNZ SCALE3 ;IS SET SO DO SCALE1
> CLR.B &P1IFG
> RETI
>
> SCALE1:
> BIT.B #1,&P2IN ;TEST P2.0, USING THE pX.0-2 BITS
> ALLOWS THE SOURCE TO USE A CONSTANT REGISTER
> RLC REG4 ;WHICH SAVES A FEW CLOCK CYCLES
> RLC REG5
> RLC REG6
> DEC REG7 ;CONTINUE TO TEST NEXT SCALE IN CASE IT
> HAS INTERRUPTED WHILE DOING SCALE 1
> BIC.B #1,&P1IFG
> RETI
>
> ETC..ETC
>
> This would make each individual interrupt take less time, but again
> scale3 would take longer than the other 2 and the cumulative time for 3
> interruptsd is longer.
>
> On timers, simply use the timer compare function, when it interrupts,
> use the foreground routine to detect it and do whatever you need to do.
>
> This is quite simplistic,a nd your code will need to be quite efficient
> to handle 3 scales. i haven't even looked at the overhead for the UART,
> but that may not be possible within the remaining 65 clock cycles. A
> stripped down but full function UART ISR, given that all the registers
> have been eaten, will take around 38 clock cycles with LPM exit, latency
> and end of packet detection. The danger then becomes the inability of
> your foreground routine to process itself in the 27 remaining clock
> cycles before the 48 bits have been collected. ie most of the foreground
> will be running a test process until either a timer expires to cancel a
> transaction or 48 bits have been collected and either a packet has to be
> sent, , so it isn't as dire as it sounds, mostly your foreground will be
> doing nothing but testing. For example a simple exampel might be:_
>
> MAINLOOP:
> TST R7 ;DO WE HAVE 48 BITS IN SCALE1
> JZ STORESCALE1
> TST R11
> JZ STORESCALE2
> TST R15
> JZ STORESCALE3
> TST TFLAGS ;1 BIT FLAGS TO INDICATE TIMER OVERFLOW
> IN A SINGLE WORD/BYTE
> JNZ DO_TIMERS ;HANDLE ANY TIMER OVERFLOW HERE
> JMP MAINLOOP
>
> STORESCALE1:
> ETC
>
> The UART doesn't necessarily need to be checked fro packet sent, but if
> it does I generally disable the RX interrupt on end of packet, and that
> could be used at the end of the MAINLOOP loop to detect and act on UART
> data sent.
>
> This is obviously a very stripped down example, and I obviously haven't
> debugged it, but with a little padding, like init codes and the routines
> to handle and manage data transmission, I don't see why it wouldn't
> work, although I would not bother trying to catch every single packet
> from the scale, i would simply collect a set of data, and then stall
> that scale until I was ready again.
>
> Hope that helps
>
> Al
>
> On 14/02/2013 6:18 PM, Yuriy's Toys wrote:
> > Hello,
> > Could someone enlighten me on what's the best approach to doing the following is:
> >
> > I need to read a set of three "Chinese calipers" connected to one of the "cheap" MSP430s (probably MSP430G2153). The calipers use a synchronous serial protocol. (On one line they provide the clock signal, and on the other - data). Once the position is read, it needs to be sent over UART to the mothership.
> > Reading one caliper is easy: I would set an interrupt on the raising edge and read the data pin in the ISR. Here is what gets me with 3 calipers:
> > 1. I need to have a timeout timer on each line to detect the period between "data streams", and if the timer overflows, reset the state machine.
> > 2. I need to have three interrupts.
> > 3. When the state machine accepts the position, I need to send it over UART.
> >
> > The question is: what is the proper way to handle all this. It looks like I will have an interrupt bonanza. If I disable the interrupts while sending the data over the slow UART, the position will miss. Same inside each position. I'd like to stick with a Launchpad part, since this is an open source "community" project, and most target users have limited experience with electronics. The only way I know how to deal with this is with an ARM MCU that supports nested interrupts and (preferably) "round robin" interrupt scheduling. Can this be done well with a "small" MSP430? If yes, I would really appreciate some guidance.
> >
> > Thank you in advance
> > Yuriy
> >
> > More details on the protocol can be found here: http://www.shumatech.com/support/chinese_scales.htm
> >
> > I'm trying to do this (different scales, same setup):
> > http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html
> >
> >
> >
> >
> >
> >
> >
> >
Raffuj,
How would I deal with having three masters talking to one slave?

Jake,
I haven't thought of DMA. Sounds like I'll be getting a good learning experience :)

Thank you
Yuriy

--- In m..., Jake G wrote:
>
> I would recommend learning the DMA, becuase the process it will take you
> to get it working will give you such an insight into how SPI should work.
>
> On 2/14/2013 8:01 AM, raffuj wrote:
> >
> >
> > Why not let the msp handle the serial data for you? You have clock and
> > data so you should be able to treat the caliper as a spi master and
> > the msp as a slave. You then only need to interrupt after every byte
> > of data or, if you use DMA, after every word or series of words.
> > Then a consumer task can wake up and process the sample(s). Another
> > task can check the state, etc.
> >
> > --- In m... ,
> > "Yuriy's Toys" wrote:
> > >
> > > Hello,
> > > Could someone enlighten me on what's the bes approach to doing the
> > following is:
> > >
> > > I need to read a set of three "Chinese calipers" connected to one of
> > the "cheap" MSP430s (probably MSP430G2153). The calipers use a
> > synchronous serial protocol. (On one line they provide the clock
> > signal, and on the other - data). Once the position is read, it needs
> > to be sent over UART to the mothership.
> > > Reading one caliper is easy: I would set an interrupt on the raising
> > edge and read the data pin in the ISR. Here is what gets me with 3
> > calipers:
> > > 1. I need to have a timeout timer on each line to detect the period
> > between "data streams", and if the timer overflows, reset the state
> > machine.
> > > 2. I need to have three interrupts.
> > > 3. When the state machine accepts the position, I need to send it
> > over UART.
> > >
> > > The question is: what is the proper way to handle all this. It looks
> > like I will have an interrupt bonanza. If I disable the interrupts
> > while sending the data over the slow UART, the position will miss.
> > Same inside each position. I'd like to stick with a Launchpad part,
> > since this is an open source "community" project, and most target
> > users have limited experience with electronics. The only way I know
> > how to deal with this is with an ARM MCU that supports nested
> > interrupts and (preferably) "round robin" interrupt scheduling. Can
> > this be done well with a "small" MSP430? If yes, I would really
> > appreciate some guidance.
> > >
> > > Thank you in advance
> > > Yuriy
> > >
> > > More details on the protocol can be found here:
> > http://www.shumatech.com/support/chinese_scales.htm
> > >
> > > I'm trying to do this (different scales, same setup):
> > >
> > http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html
> > >
> >
> >
>

The launchpad parts (MSP430) don't have DMA, or didn't last time I
looked. Also the DMA on the MSP430 has just 3 channels, and, although
some of the larger parts have 3 SPI channels you are certainly well out
of Launchpad range. In a very busy system the DMA can be a bigger
problem than those it solves, in my experience, as it isn't a true CPU
independent DMA.

The SPI idea seems like a good one, although I haven't really burrowed
right into it, provided you can realistically guarantee syncing to the
start of each transmission. If you have aLaunchpad then test it out
first using the SPI on the USCI B module. doing things in byte sized
chunks increases the time between interrupts to 64usecs, which is plenty
of time, though if you keep it bare bones I still feel that the smaller
parts like the 2xx3 series are goign to be able to cope.

Cheers

Al

On 15/02/2013 6:08 AM, Yuriy's Toys wrote:
> Raffuj,
> How would I deal with having three masters talking to one slave?
>
> Jake,
> I haven't thought of DMA. Sounds like I'll be getting a good learning experience :)
>
> Thank you
> Yuriy
>
> --- In m..., Jake G wrote:
>> I would recommend learning the DMA, becuase the process it will take you
>> to get it working will give you such an insight into how SPI should work.
>>
>> On 2/14/2013 8:01 AM, raffuj wrote:
>>>
>>> Why not let the msp handle the serial data for you? You have clock and
>>> data so you should be able to treat the caliper as a spi master and
>>> the msp as a slave. You then only need to interrupt after every byte
>>> of data or, if you use DMA, after every word or series of words.
>>> Then a consumer task can wake up and process the sample(s). Another
>>> task can check the state, etc.
>>>
>>> --- In m... ,
>>> "Yuriy's Toys" wrote:
>>>> Hello,
>>>> Could someone enlighten me on what's the bes approach to doing the
>>> following is:
>>>> I need to read a set of three "Chinese calipers" connected to one of
>>> the "cheap" MSP430s (probably MSP430G2153). The calipers use a
>>> synchronous serial protocol. (On one line they provide the clock
>>> signal, and on the other - data). Once the position is read, it needs
>>> to be sent over UART to the mothership.
>>>> Reading one caliper is easy: I would set an interrupt on the raising
>>> edge and read the data pin in the ISR. Here is what gets me with 3
>>> calipers:
>>>> 1. I need to have a timeout timer on each line to detect the period
>>> between "data streams", and if the timer overflows, reset the state
>>> machine.
>>>> 2. I need to have three interrupts.
>>>> 3. When the state machine accepts the position, I need to send it
>>> over UART.
>>>> The question is: what is the proper way to handle all this. It looks
>>> like I will have an interrupt bonanza. If I disable the interrupts
>>> while sending the data over the slow UART, the position will miss.
>>> Same inside each position. I'd like to stick with a Launchpad part,
>>> since this is an open source "community" project, and most target
>>> users have limited experience with electronics. The only way I know
>>> how to deal with this is with an ARM MCU that supports nested
>>> interrupts and (preferably) "round robin" interrupt scheduling. Can
>>> this be done well with a "small" MSP430? If yes, I would really
>>> appreciate some guidance.
>>>> Thank you in advance
>>>> Yuriy
>>>>
>>>> More details on the protocol can be found here:
>>> http://www.shumatech.com/support/chinese_scales.htm
>>>> I'm trying to do this (different scales, same setup):
>>>>
>>> http://www.yuriystoys.com/2012/09/arduino-bluetooth-module-wireless-dro.html
>>>
>>
>>

The 2024 Embedded Online Conference