Go Down

Topic: Help with running Arduino sketch not built for a Arduino Due (Read 6772 times) previous topic - next topic

mrdude

Hi guys I am very new to Arduino - infact I am an Arduino virgin - lol.

I have got a Udoo quad board which contains a built in Arduino Due, I have tested the blink project and it works great - so I know my pc can send a sketch to the board and it works fine.

I downloaded the following project - sketch and get an error when trying to send it to the arduino, The sketch is here:

https://github.com/zoobab/tjtag-arduino/blob/master/tjtag3-0-1_JTMOD/arduino/arduiggler.pde

I get the following error:

arduiggler.pde: In function 'void loop()':
arduiggler.pde:92: error: 'PORTD' was not declared in this scope


How can I make this work on the Arduino Due, without getting the errors? Thanks.

graynomad

#1
Dec 28, 2013, 06:25 am Last Edit: Dec 28, 2013, 06:33 am by Graynomad Reason: 1
PORTD is an AVR-specific macro. I would say it's not possible to use that code without re-writing all the AVR-specific parts. If you are lucky that will only be a few lines. Either that or get onto the person who wrote the code and see if they plan to upgrade it.

This in IMO is big problem that will only get bigger as the number of variants grows.


EDIT: OK I've just looked at the code, it seems that the only problem is this line

   
Code: [Select]
          // Set output pins to requested values.
                PORTD = (unsigned char)( (byte & B00011111) << 2 );


As long as speed is not a real concern that could be replaced with 8 digitalWrite() calls to pins 0-7.

Oh, and there is another possible gotcha, the assignment to PORTD sets all 8 bits at the same time, 8x digitalWrite() does not. What does this code do? It appears to be testing a JTAG cable or something so this might be an issue.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

EliteEng

As Graynomad said this code is AVR specific and will need to be changed.
   
Code: [Select]
          // Set output pins to requested values.
                PORTD = (unsigned char)( (byte & B00011111) << 2 );


This could be very easy  to change

You will need to know what pins/ports  it is using on the ARM processor ( Due )  if it is using pins on the same port you can simply write to the port SIMILAR to the AVR code.

If the pins are on a couple of different ports you will have to do a couple of writes to the ports.

If you find out the pins, I can help with the code

mrdude

Thanks for the replies guys - yes I am just going to use the same pins on the Arduino Due (2-7), I have tested these pins are ok by making them turn a sainsmart 8 relay board on and off so I know they are all ok.

Like I said above - I am an arduino noob, I have just got the Arduino for dumies book and downloaded some projects to learn - so my skills on programming this board are nil as yet.

I have used this jtag program before (pc version) and know how to hook the Arduino to the jtag points - also the windows command prompts etc.

All I really need is a help with what Arduino code to write -  ie how would I change the error above to do the:

8 digitalWrite()

I had a look here:
http://www.hobbytronics.co.uk/arduino-tutorial4-cylon

And from what I can see, this program was written for the Arduino Uno - which looks like it sets pins on 'port d', which I assume is pins 0-7 on the Arduino Uno to the following:

0 - Output
1 - Output
2 - Output
3 - Output
4 - Output
5 - Input
6 - Input
7 - Input

I have no idea what the part of the code that says 'byte &' and the part that says '<< 2 ' does. Like I say I am completely new to this so any help would be appreciated - Speed shouldn't be an issue though so if someone could point out how to do the code to set those pin values that would be appreciated.

Thanks.

graynomad

PORTD on the Uno is pins D0-7, the same logical pins on the Due are

A.8, A.8, B.25, C.28, C.26, C.25, C.24, C.23

In other words it's a bit of a dog's breakfast that spans 3 ports.

This can be done but there is a crucial question to answer first, "Do all the bits have to change at the same time?" If the answer is "yes" then you better go buy a Uno or use different pins on the Due.

There's no point writing code that uses 8 digitalWrites()s before this is settled.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

jstampfl

Code: [Select]
         // Set output pins to requested values.
                PORTD = (unsigned char)( (byte & B00011111) << 2 );


In this case "byte", which is a reserved word, is used as a variable.   It receives a value from the PC.  I would change to some other name such as "pcin". 

So the earlier line:

                unsigned char byte = Serial.read();

would change to:

               unsigned char pcin = Serial.read();

The original works but is confusing.

So in this program, the value of pcin can be 0 - 255, ie.  8 bits worth.  ie:  B00000000 - B11111111

                the  (pcin & B00011111) masks to the lowest 5 bits, or values  0-31.  ie:  B00000000 - B00011111

                      the "<< 2"  shifts the result 2 bits to the left.  sets :  none, or one or more of pins 2 - 7

So the effect would be to set the corresponding pins of PORTD to: all LOW, or some combination of pins 2 - 7  HIGH.

I will look at doing this on the DUE and post my results.



mrdude

Thanks guys you have been very helpful. @jstampfi - that info you have posted explains things nicely, and yes I would appreciate if you could do this on your Due and post the results.

Thanks again.

jstampfl

Here are two programs that use direct writes to turn on and off LED's connected to an Arduino Due.

The first example, controls LEDs on pins 2 - 6.  Takes one or two direct writes since pin2 is on port B and pins 3 - 6 are on port C.

the second example moves the LEDS to pins 3 - 7.  This can be done with one direct write since all the pins are on port C

Code: [Select]
//EXAMPLE1
//example of blinking LEDs connected to pins 2 - 6 on an Arduino DUE
//    this uses 1 or 2 direct writes, if pin 2 is included takes 2 direct writes.
//    if you can move to pins 3 - 7 it only needs one direct write, see next example

unsigned char pcin = 31;   //simulate input from Serial.read
unsigned char pcinr = 0;    //working variable for pin selection
unsigned long mypin2 = (1u << 25);  //  sets 32bit mypin2 to be Sam's pin value for Arduino Due pin2. (combined later with port selection.
void setup() {
  // put your setup code here, to run once:
  //Serial.begin(115200);  //to see the pcin & pcinr values, uncomment here and the Serial.write below
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  digitalWrite(2,LOW);
  digitalWrite(3,LOW);
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
         
  delay(2000);
}

void loop() {
  // Note the pin mapping on the Arduino Due.  See the pin map from the Arduino.cc product page, Arduino Due
  //                                          Arduino Pin              Sam/Due internal pin
  //                                               2                        PB25              B register pin 25
  //                                               3                        PC28              C register pin 28
  //                                               4                        PC26              C register pin 26  NOTE: gap of one between 3 & 4
  //                                               5                        PC25              C register pin 25
  //                                               6                        PC24              C register pin 24
          pcinr = 0;
          if (pcin & B00010000) {  // Pin 6              PC24
            pcinr |= B00000001;    // reverse to because the assigned pins PC28 - PC24 count down
          }
          if (pcin & B00001000) {  // Pin 5              PC25
            pcinr |= B00000010;
          }
          if (pcin & B00000100) {  // Pin 4              PC26
            pcinr |= B00000100;                     
          }
          //  skips                                      PC27
         
          if (pcin & B00000010) {  // Pin 3              PC28
            pcinr |= B00010000;
          }

   
         
     
         if (pcin & B00000001) {    // Pin 2 
         REG_PIOB_SODR = mypin2;    // PIOB means port B.  So needs to be separate.  SODR is the write HIGH register
         }
         REG_PIOC_SODR = (((unsigned long)(pcinr)) << 24);  // write Pins 3 - 6 in PIOC, port C.
         delay(1000);
         if (pcin & B00000001) {
         REG_PIOB_CODR = mypin2;                            //  CODR to write LOW
         }
         REG_PIOC_CODR = (((unsigned long)(pcinr)) << 24);
         //Serial.println(pcin,BIN);
         //Serial.println(pcinr,BIN);
        delay(1000);
}


Here is example 2:

Code: [Select]
//EXAMPLE2
//example of blinking LEDs connected to pins 3 - 7 on an Arduino DUE
//    this uses 1 direct write.


unsigned char pcin = 31;   //simulate input from Serial.read
unsigned char pcinr = 0;    //working variable for pin selection
unsigned long mypin2 = (1u << 25);  //  sets 32bit mypin2 to be Sam's pin value for Arduino Due pin2. (combined later with port selection.
void setup() {
  //Serial.begin(115200);  //to see the pcin & pcinr values, uncomment here and the Serial.write below
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  digitalWrite(3,LOW);
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);
         
  delay(2000);
}

void loop() {
  // Note the pin mapping on the Arduino Due.  See the pin map from the Arduino.cc product page, Arduino Due
  //                                          Arduino Pin              Sam/Due internal pin
  //                                               2                        PB25              B register pin 25
  //                                               3                        PC28              C register pin 28
  //                                               4                        PC26              C register pin 26  NOTE: gap of one between 3 & 4
  //                                               5                        PC25              C register pin 25
  //                                               6                        PC24              C register pin 24
          pcinr = 0;
          if (pcin & B00010000) {  // Pin 7         PC23
            pcinr |= B00000001;    // reverse to because the assigned pins PC28 - PC23 count down
          }
          if (pcin & B00001000) {  // Pin 6         PC24
            pcinr |= B00000010;
          }
          if (pcin & B00000100) {  // Pin 5         PC25
            pcinr |= B00000100;
          }
          if (pcin & B00000010) {  // Pin 4         PC26
            pcinr |= B00001000;
          }
          if (pcin & B00000001) {  // Pin 3          Sam/Due internal PC28, skip one form pin 4
            pcinr |= B00100000;
          }
   
         
     

         REG_PIOC_SODR = (((unsigned long)(pcinr)) << 23);  // write Pins 3 - 7 HIGH in PIOC, port C.
         delay(1000);
 
         REG_PIOC_CODR = (((unsigned long)(pcinr)) << 23);  // write LOW
         //Serial.println(pcin,BIN);
         //Serial.println(pcinr,BIN);
        delay(1000);
}

mrdude

Thanks very much friend - I will have a look at these programs so I can try and understand what's going on. I guess that's me going to be busy all day tomorrow - haha.

Regards, and thanks for taking the time to post this.

EliteEng

If there is no requirement to keep them on the same pins ( ie a shield ) I would move them to pins 34-39 and use something like the following code

Code: [Select]
/* Arduino Wiggler Cable Simulator */
/* Intended for use with tjtag3-0-1 with JTMOD patch. */


#define WRSTN 34  //C2
#define WTMS 35   //C3
#define WTCK 36   //C4
#define WTDI 37   //C5
#define WTRSTN 38 //C6
#define WTDO 39   //C7

#define PIN_MASK (g_APinDescription[WRSTN].ulPin | g_APinDescription[WTMS].ulPin | g_APinDescription[WTCK].ulPin | g_APinDescription[WTDI].ulPin | g_APinDescription[WTRSTN].ulPin)
#define PIN_PORT g_APinDescription[WRSTN].pPort // Digital Pins 34-39 are port C on the Arduino Due

typedef
enum __arduOp
{
    OP_RESET = 0,
    OP_SEND  = 1,
    OP_READ  = 2,
    OP_RSVD  = 3
}
arduOp;                                                                                                                                                     

void pinOutputLow(uint32_t ulPin)
{
   PIO_Configure( g_APinDescription[ulPin].pPort, PIO_OUTPUT_0, g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ;
}

void setup(void)
{
    // Pins 0-7 are part of PORTD
    // pins 0 and 1 are RX and TX, respectively

    PIN_PORT->PIO_WPMR = PIN_MASK; // Disable Write Protection on Pins
    PIN_PORT->PIO_OWER = PIN_MASK; // Enable Writing to All pins at once
 
    pinOutputLow(WRSTN);    // WRST_N
    pinOutputLow(WTMS);     // WTMS
    pinOutputLow(WTCK);     // WTCK
    pinOutputLow(WTDI);     // WTDI
    pinOutputLow(WTRSTN);   // WTRST_N

    pinMode(WTDO, INPUT);      // WTDO

    //Serial.begin(9600);
    Serial.begin(115200);

    /*
     * Before starting...
     * Say something invalid so that if the Arduino
     * gets reset in the middle of a run, the tjtag
     * program will know that something's gone wrong.
     *
     * This is invalid because our simple protocol
     * says that bits 6-0 should never be set except
     * when responding to a reset command with 0x42.
     */
    Serial.write(0x7F);
}

void loop(void)
{
    // Wait until byte available.
    while ( ! Serial.available() );

    int value = Serial.read();
    unsigned char pcin = value;

    //Serial.print("byte received: ");
    //Serial.println(pcin, HEX);

    unsigned char op = (pcin & B01100000) >> 5 ;

    //Serial.print("opcode interpreted: ");
    //Serial.println(op, HEX);


    switch ( op )
    {
        case OP_RESET:
            {
                //Serial.println("  OP_RESET");
                // Clear all outputs.
                digitalWrite(WRSTN, LOW);
                digitalWrite(WTMS, LOW);
                digitalWrite(WTCK, LOW);
                digitalWrite(WTDI, LOW);
                digitalWrite(WTRSTN, LOW);

                // Respond that we're ready to go.
                Serial.write(0x42);

                // Clear out any other incoming data.
                Serial.flush();
            }
            break;
           
        case OP_SEND:
            {
                //Serial.println("  OP_SEND");

                // Set output pins to requested values.
                // PORTD = (unsigned char)( (pcin & B00011111) << 2 );
                PIN_PORT->PIO_ODSR = (PIN_PORT->PIO_ODSR & ~(PIN_MASK)) | ((pcin & B00011111) << 2 );
                // If needed:  put a Serial.write() here so that
                // we can "wait" for the pins to be set.
                Serial.write(0x4B);
            }
            break;

        case OP_READ:
            {
                //Serial.println("  OP_READ");

                unsigned char readByte = digitalRead(WTDO) == HIGH ?     // WTDO
                                            B10000000 :     // send back a 1 in bit 7
                                            B00000000;      // send back a 0 in bit 7

                Serial.write(readByte);
            }
            break;

        default:
            {
                // BAD OPCODE
                // Send invalid data in response.
                Serial.write(0x7F);
            }
    };

    //Serial.println();
    //Serial.println();
}


This is untested but should work, as I don't know what this sketch is used for there is no error checking.

Let me know if it works, or if changes are needed.

mrdude

@EliteEng

Yes, thank you it works great - I am able to use this now and have tested it on a 64 bit version of windows 7.

What this does:

If you have a linksys router (or other equipment detected by this program) with a JTAG port - you can use this to flash/recover the flash memory (where the firmware is stored). Previously I could only do this with a USB Jtag - but it was very buggy and didn't work on a 64 bit O/S.

I had an old PC with a printer port and was able to do it this way - but it was a pain to get that out the attic and set it up just to de-brick something.  This saves me doing this now, so thank you for that.

This code is working on the Udoo board which contains a built in Arduino Due - If you don't mind I will post this on DD-WRT forums and the Udoo forums - obviously, I will credit you and others who made the original software if you don't mind me sharing your code.

Once again - thank you very much, I appreciated this a great deal and for the other people posting in here trying to help. I wish you all the best for the upcoming year.


mrdude

@eliteEng:

Thanks, you have probably saved a lot of people quite a bit of money and a few routers from the bin - once again, thanks very much, this will be appreciated by a lot of people. :-)

EliteEng

@mrdude

If anyone felt like making a donation, we accept them at  http://www.microcnc.net

microCNC is a CNC Controller using the Arduino Due

Go Up