From: Mikael Nordman on
Fevric J. Glandules wrote:
> Hi all,
>
> I am new to this group but checking over recent postings seems
> to indicate a fair amount of Clue kicking around [1].
>
> A bit of background before y'all tell me to RTFM or JFGI.
>
> I've got quite a lot of experience in programming 8 bit microcontrollers
> with assembler; I've also done quite a lot of 32 bit embedded stuff
> using an RTOS with C. What's new to me is using a 16 bit mid-range
> PIC18 device in C.
>
> So I'm trying to make sure that I come up with a fairly sensible
> architecture. Googling isn't much help - most of the "tutorial"
> stuff out there is aimed at a very low level, or else you find
> discussion at the nuts and bolts level of a particular interrupt
> handler.
>
> The application is probably fairly typical - inputs / commands
> come in via the UART, peripheral devices need to be turned on
> and off in response, other devices need to be queried via I2C
> for data, etc.
>
> My current thinking is to have a main() loop that is subdivided
> into separate sections that deal with each peripheral in turn.
>
> Each code block will be non-blocking, and will implement a
> state machine for each peripheral. Incoming comms will run
> off interrupts. In RTOS terms, a sort-of round-robin system.
>
> If, for example, incoming commands are ASCII sequences
> like "L11" for "LED 1 on" followed by an end-of-message
> checksum byte, in pseudo-code, something like this:
>
> uart_isr() { // push chars into circular buffer
> push_char_to_uart_buf()
> if (char == end_of_message) message_flag = 1;
> }
>
> main_loop {
> if (message_flag) {
> move_chars_from_uart_buf_to_command_buf()
> switch (command) {
> case foo: foo_state = 1;
> case bar: bar_state = 1;
> }
> }
> // foo machine
> if (foo_state) {
> switch (foo_state) {
> case 1: if (foo1()) foo_state = 2;
> case 2: if (foo2()) foo_state = 0;
> }
> // bar machine
> if (bar_state) {
> switch (bar_state) {
> case 1: if (bar1()) bar_state = 2;
> case 2: if (bar2()) bar_state = 0;
> }
> }
>
> Does that make sense? Should the ISR do as little as possible or
> is it a good idea to give it some "awareness"?
>
> The above pseudo-code is just meant to give an idea of where
> I'm heading, so don't take it too seriously. I'm really looking
> for general pointers on how to approach a mid-level architecture.
>
> Oh go on then, rip me to shreds.
>
> [1] I've also dug out the FAQ.
>
Even if you want to use C, may I suggest FlashForth, a 16 bit Forth Operating
System for the PIC18/PIC30/soonPIC24. It has an inbuilt command interpreter and
compiler. It also has an round robin multitasker allowing you to
have background tasks in addition to the operator task.
Forth code for I2C is provided as an example.

With the compiler you design new command langauges to your liking.
These new commands can then interpreted by the interpreter.

http://flashforth.sourceforge.net/

-- Mikael

From: Neil on
Vladimir Vassilevsky wrote:
>
>
> Neil wrote:
>
>> Vladimir Vassilevsky wrote:
>>
>>
>>> It is so much easier to use a basic time-slicing round robin
>>> preemptive multitasker rather then developing the complicated
>>> non-blocking state machines. Then, the tasks can be done as the
>>> straightforward linear code, and you don't have to worry about blocking.
>>>
>> In a PIC18 ?
>
> What's the use of PICs or 8051x misery when AVRs, HC08s and other
> processors with the flat memory and the traditional stack are available?
>
>
> Vladimir Vassilevsky
> DSP and Mixed Signal Design Consultant
> http://www.abvolt.com
>
If you can live with out an RTOS. Mature tools, lots of fourms, lots of
code samples, A bigger selection of parts, dirt cheap.
Sometimes a cheap lame CPU fits the bill.
From: Neil on
Joe Chisolm wrote:
> On Thu, 10 Sep 2009 21:06:26 +0000, Fevric J. Glandules wrote:
>
>> nospam wrote:
>>
>>> PIC18s are 8 bit processors.
>> So they are. I've spent enough time with the datasheet and looking at
>> example assembler and my own disassembled C code that you'd think it
>> would have percolated back to my consciousness by now. Mind, it was
>> quite late when I wrote that.
>
> I have found there are several coding constructs that help the MPLAB
> compiler create tighter code. Define a bit field for logical flags.
> The compiler will emit BTFSS, BTFSC instructions. If you use a full
> byte the compiler will emit a MOVF to W and test instructions. If
> you have something like:
> flag = 0;
> ....
> flag = 1;
> ....
> if (flag != 0) ...
>
> you can save a couple of instruction words by using flag += 1 instead of
> the flag=1. This is because the compiler will generate a INCF instruction
> instead of a MOVLW and MOVWF.
>
> Many times a switch statement will generate cleaner code than using a
> if/elsif/else
>
> The compiler does a lot of work dealing with pointers and pushing
> arguments on the stack.
>
> If I start running low on program memory I'll usually try different coding
> constructs and look at the assembly listing to find the best generated
> code.
>
Or you could use bit vatiables.