Download your favorite Linux distribution at LQ ISO.
Go Back > Forums > Non-*NIX Forums > Programming
User Name
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.


  Search this Thread
Old 12-14-2017, 04:23 AM   #1
LQ Newbie
Registered: Dec 2017
Posts: 1

Rep: Reputation: Disabled
C program acts as a three wire master under Linux

I often use the Parallel port (D-Sub DB-25 female) of PC to communicate with MCU or a processor card with my unique and self developed software and interface circuit .

Now it looks like I've found a functional bug in the USI hardware of AVR ATtiny45/85 MCU.

I wanted to read the received bytes from the USIBR register instead of USIDR to take advantage of what was being written in data sheet of Atmel (today Microchip's). Here is a quote from 2586Q–AVR–08/2013 data sheet of ATtiny25/45/85:
" Instead of reading data from the USI Data Register the USI Buffer Register can be used. This makes controlling the USI less time critical and gives the CPU more time to handle other program tasks. USI flags as set similarly as when reading the USIDR register. The content of the USI Data Register is loaded to the USI Buffer Register when the transfer has been completed. "
I would like to show and proof with my experiment that the USIBR is unusable in the ATtiny45/85 chips, because it loses the MSB bit of the received byte. E.g: if the value of received byte is 3 then 7 is readable from USIBR, if received byte is 4 then the result is 8 from the USIBR.

Generally form is: if the received byte:n then ( (n<<1) + (1&n) )&0xff is readable from USIBR. (It is like a "backward arithmetic shift".)

In my demonstration I used USI in three wire and slave mode and I connected the chip to the Parallel port of my PC via 1kOhm resistors, and I used 5V from a USB plug. And I used the inside calibrated oscillator in default mode 8MHz with CKDIV8 fuse so speed was 1usec/1instruction (if it is one cycle instruction.) The accurate pin assignment between PC and ATtiny45 ("the interface circuit") has been seen top of my C program in a comment.

This C program in the PC acts as a three wire master under Linux. It uses very slow clock: 1ms for half period and wait 10ms between bytes. This master sends the series of one byte integers to the slave. The slave assembly program in the chip only echoes back to the received bytes and the master gets this echo and print them on the screen. Of course the received byte was coupled with the previously sent byte in the printed string.

The master and slave program demonstrates the successful operation when I use the "IN R16,USIDR" line in slave. But if I change this one line to "IN R16,USIBR" then the echo from the slave to the master is satisfies the above strange form that means the MSB had been lost in USIBR. I think we can conclude that USIBR is unusable.
Please look at my sources. I tried to keep the source code as short as possible both in C and assembly. And I put the two Intel HEX outputs also for the clarity. This also shows that only one instruction word was different in the slave program (B10F is godd case but B300 isn't working (data part of Intell HEX is little endian)).


I'm going to send a bug report to Microchip from this, because this problem isn't in the Errata of the last 2586Q–AVR–08/2013 data sheet.

I wonder if anyone can confirm the problem of USIBR or refute it?
Here is the Echo prg (slave on three wire):

; This is a slave on 3 wire
; and echo back the received bytes.

        .EQU   OK = 1       ;If OK=1 then "in a,usidr",
                            ;If OK=0 then "in a,usibr" will be compiled 
        .include   "/usr/share/avra/"
;       .device ATtiny45
        .def    a =  r16
        .org    0x0000       ;IT vector not used
        bclr    sreg_i       ;disable IT forever
        sbi     ddrb, ddb1   ;DB1(MISO) is output, all other is input

        ldi     a, 0x18     ;SIE:0 OIE:0 WM1:0 WM0:1 CS1:1 CS0:0 CLK:0 TC:0
        out     usicr, a    ;set USI to three wire as slave

cyc0:   sbi     usisr, usioif   ;clr USIOIF
cyc1:   sbis    usisr, usioif   ;skip if received a byte
        rjmp    cyc1            ;wait for a byte from master

        .IF     OK
        in      a, usidr        ;get the byte from usidr
        in      a, usibr        ;get the byte from usibr it's DON'T working

        out     usidr, a        ;echo back the received byte
        rjmp    cyc0            ; do forever

;  If .EQU OK = 1 then Intel HEX output this: and USIDR is used successful
;  :020000020000FC
;  :10000000F894B99A08E10DB9769A769BFECF0FB1B4
;  :040010000FB9FACF5B
;  :00000001FF

;  If .EQU OK = 0 then Intel HEX output this: but USIBR is used with FAULT
;  :020000020000FC
;  :10000000F894B99A08E10DB9769A769BFECF00B3C1
;  :040010000FB9FACF5B
;  :00000001FF
If .EQU OK = 1 in the above source, then the part of output screen of master.c
Received: 00 == Previously sent: 00
Received: 01 == Previously sent: 01
Received: 02 == Previously sent: 02
Received: 03 == Previously sent: 03
Received: 04 == Previously sent: 04
If .EQU OK = 0 in the above source, then the part of output screen of master.c
Received: 00 == Previously sent: 00
Received: 03 != Previously sent: 01
Received: 04 != Previously sent: 02
Received: 07 != Previously sent: 03
Received: 00 != Previously sent: 80
Received: 03 != Previously sent: 81
Received: 04 != Previously sent: 82
Received: 07 != Previously sent: 83
Received: e8 != Previously sent: f4
Received: eb != Previously sent: f5
Received: ec != Previously sent: f6
Received: ef != Previously sent: f7
Finally, here is my C program acts as a three wire master under Linux via Parallel port of PC.
Test of three wire between PC & ATtiny45

  This prg acts as master of 3wire.
  It sends series of byte 0, 1, 2 ...
  And it prints the received and
  that was sent in before.

  Pin connection between PC and ATtiny45:
  PC Parallel port
  D-Sub DB-25 Female              ATtiny45
  PORT.D0 (pin2) --> 1kOhm --> PB0 (pin5) (MOSI)
  PORT.D1 (pin3) --> 1kOhm --> PB2 (pin7) (SCK)
  (PORT+1).D6 (pin10) <-- 1kOhm <-- PB1 (pin6) MISO
  PORT.D2 (pin4) --> 1kOhm --> PB5 (pin1) ~RST
  GND (pin25) -------------------GND (pin4)

  Power is 5V (from a USB plug).
  And inside calibrated oscillator was used
  in default mode (8MHz and div8) so
  1usec/one instruction (if it is one cycle).

gcc -O0 three_wire_test.c -o three_wire_test -lrt

If you want to use this prg by a normal user:
chown root:laci three_wire_test && chmod +s three_wire_test

#include <stdio.h>
#include <stdlib.h>
#include <sys/io.h>
#include <sys/time.h>

#define PORT    0x378      //Others: 0x278 0x3bc

//very slow clock
#define W100    100000     // 100ms reset
#define W1      1000       // 1ms half ck
#define W10     10000      // 10ms after a byte transfer

void wait_u(int);
int snd_rec_byte(int);

int main(){
int i, snt, snt_1, rec;

// Get permission for direct I/O under Linux:
    printf("Couldn't open parallel port 0x%x\n", PORT); exit(1);}

//One reset pulse 
outb(4, PORT); wait_u(W100); outb(0, PORT); wait_u(W100);
outb(4, PORT); wait_u(W100); // waiting for startup of chip

// send, receive and print bytes
for(snt_1=-1, snt=0; ;snt_1=snt, snt++, snt&=0xff){
    if(snt_1!=-1)printf("Received: %02x %s Previously sent: %02x\n",\
                         rec, rec==snt_1?"==":"!=", snt_1);}
} //End of main

int snd_rec_byte(int s){                 // One byte send & receive
int r, i;
for(r=i=0 ; i<8; i++, s<<=1){            // 8 bit shifting
    outb(s&0x80?5:4, PORT); wait_u(W1);  // hold SCK=L,MOSI=MSBofs; wait 1ms
    outb(s&0x80?7:6, PORT); wait_u(W1);  // rise SCK=H,hold MOSI; wait 1ms
    r<<=1; if(inb(PORT+1)&0x40)r|=1;     // MISO shift into r,outputs unchanged
    outb(s&0x80?5:4, PORT); wait_u(W1);} // fall SCK=L,HOLD MOSI, wait 1ms
wait_u(W10); return(r);
} // End of snd_rec_byte

void wait_u(int c){                      // Delay minimum c usec
struct timeval req, req2;
gettimeofday (&req, NULL);
    gettimeofday (&req2, NULL);
    if((req2.tv_sec-req.tv_sec)*1000000+req2.tv_usec-req.tv_usec >= c)return;}
} // End of wait_u
Old 12-15-2017, 02:31 AM   #2
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 3,608

Rep: Reputation: 1105Reputation: 1105Reputation: 1105Reputation: 1105Reputation: 1105Reputation: 1105Reputation: 1105Reputation: 1105Reputation: 1105
I know nothing about this (or any other) chip, but I think you might have found a 'bit-collecting register': the bits might enter in LSB->MSB order; when the first bit-value arrives it fills every bit-positions, then when a new bit arrives, the value is shifted right, and the new bits enter as (temporary) MSB:

input result
b0    b0 b0 b0 b0 b0 b0 b0 b0
b1    b1 b0 b0 b0 b0 b0 b0 b0
b2    b2 b1 b0 b0 b0 b0 b0 b0
b3    b3 b2 b1 b0 b0 b0 b0 b0
b4    b4 b3 b2 b1 b0 b0 b0 b0
b5    b5 b4 b3 b2 b1 b0 b0 b0
b6    b6 b5 b4 b3 b2 b1 b0 b0 -- you got this value
b7    b7 b6 b5 b4 b3 b2 b1 b0 -- complete byte: you wished to get this

Last edited by NevemTeve; 12-15-2017 at 06:46 AM.


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Preventing program to change master volume in alsa iwtbf Linux - General 1 04-14-2014 01:35 PM
why video card acts differently in linux exbootie Linux - Newbie 4 11-29-2005 02:34 PM
whats a good program to backup my master boot record FocusedWolf Linux - General 11 03-15-2005 10:55 PM
Any Linux browser acts like IE? chriscyl Linux - General 22 08-05-2002 10:49 AM
Any Linux browser acts like IE ? chriscyl Linux - Newbie 3 08-03-2002 07:05 PM > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:53 PM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration