Teensyduino 1.38 Beta #2

Status
Not open for further replies.
They already are as far as I know. I added that support awhile ago. I have run SPI display using an adapter I plug into the SD card slot.
They are pins 58-62, and I verified code in Serial2 and Serial4.

Likewise I verified pins 58 and 59 are in table for Wire1.
 
I had no idea about that, thanks guys. SPI makes sense (brain fart), but is I2C on pte0,1 mapped too?
Edit: "I2C1: SCL/SDA" awesome
 
Last edited:
New Libs

I would recommend TeensyThreads as well as NeoGPS. Both work great with the Teensy. NeoGPS is already downloadable the lib manager in Arduino IDE.

Thanks
Mike
 
More of question on the compiler than an issue. I am getting warnings during compile that variables are declared but not used. However, when I go into the code to check the variables are used but are used in "if-else" statements. Is there a way to fix this? I did try compiling with different options (not all of them) but got the same error.

Thanks
Mike
 
More of question on the compiler than an issue. I am getting warnings during compile that variables are declared but not used. However, when I go into the code to check the variables are used but are used in "if-else" statements. Is there a way to fix this? I did try compiling with different options (not all of them) but got the same error.

Thanks
Mike

That is typical for situations where not all cases are covered by (if,if-else,else)
I found this warning useful to verify the logic behind the program.
Fix: cover all cases
 
More of question on the compiler than an issue. I am getting warnings during compile that variables are declared but not used. However, when I go into the code to check the variables are used but are used in "if-else" statements. Is there a way to fix this? I did try compiling with different options (not all of them) but got the same error.

Thanks
Mike

This is a feature, not a bug. If the only place where you set a variable is inside of the then part of an if-then-else statement, but you use it outside of the if-then-else statement, then the value is unset if the else condition was set.

So if your code is the following, a could be 0, -53, or any value depending what previous functions left in that stack location, or in the register chosen:

Code:
void foo (void)
{
  int a;

  if (condition ()) {
    a = 1;
    // ..
  } else {
    // ...
  }

  // ...
  if (a) { ... }
}

Now, one way to solve this is to initialize the variable when it is declared.

Code:
void foo (void)
{
  int a = 0;

  if (condition ()) {
    a = 1;
    // ...
  } else {
    // ...
  }

  // ...
  if (a) {
    // ...
  }
}

Or in the else statement, you can provide a value:

Code:
void foo (void)
{
  int a;

  if (condition ()) {
    a = 1;
    // ...
  } else {
    a = 0;
    // ...
  }

  // ...
  if (a) {
    // ...
  }
}
Another way is to move the scope of a into the if-then-else:

Code:
void foo (void)
{

  if (condition ()) {
    int a = 1;

    // ..

    if (a) {
      // ...
    }
  } else {
    // ...
  }
}
 
Last edited:
Thanks Michael. Figure Option 2 would resolve the warning but was trying to understand the compiler warnings. Didn't think it was a bug. Because of what I am doing I will probably go with this option (just initializing the variable at the beginning of the function). I did check the logic and all cases were covered as wmxz suggested.

If anyone is using the Adafruit Motor Shield library, they are going to be seeing a lot of these warnings. The library covers the shields ability to use dc motors, steppers and servos. So if you use just the dc motor option the stepper functions throw a lot of these warnings. Probably should post it on GitHub.

Thanks again.

EDIT: Interesting. Did that then I get another warning about the variables being set but not used. Have to do a double check but they are defined within if-then-else statements. Have to rethink the logic I guess.
 
Last edited:
@Paul - Any progress on the adding storage for Serial buffer design/code? I know it was talked about on the Arduino mailing list maybe 2+ months ago.
Also you mentioned it up on the forum thread: https://forum.pjrc.com/threads/44540-C-Teaching-old-dog-new-tricks?p=146849&viewfull=1#post146849

Is this something you wish to get into this release?

If so, do you see it at least currently stay with C code for each UART or do you see it converting over to maybe something like we did to Wire and SPI objects, where one class, with hardware data structure passed in for each instance?

My assumption is you do not wish to have the class allocate (malloc, new, ...) the buffer, but instead wish to pass in pointer, size (or helper class). Do we do it on new method(s) like:
Code:
Serial.addStorageForRead(void *buffer, size_t length);
Serial.addStorageForWrite(void *buffer, size_t length);
Or the other way of having additional begin methods where you can pass them in?

And if yes to any of this do you want some help on it?
 
@Paul - Any progress on the adding storage for Serial buffer design/code?

Nope, but it's on my todo list...

Is this something you wish to get into this release?

And if yes to any of this do you want some help on it?

Yes, if you'd like to work on this, I've love to merge it. We're going to need quite a bit of time for testing, so now's probably a pretty good time since Arduino 1.8.4 seems quite a long way off. But if they do release unexpectedly, we'll need to revert to the old code and push this to a future version...

If so, do you see it at least currently stay with C code for each UART or do you see it converting over to maybe something like we did to Wire and SPI objects, where one class, with hardware data structure passed in for each instance?

Converting the serial code to the same single-class approach with const tables for the hardware details has also been on my wish list.

Honestly, I'm a little nervous about doing both at the same time.

Or the other way of having additional begin methods where you can pass them in?

I know at one point I talked about an addMemoryForReceive() function, but after thinking about this more, I believe it's cleaner to do it by overloading begin(). Still not sure if we should do with with C++ wrapper classes as Martino proposed, or just pointers and size.
 
Hi Paul (and others),

I am playing around with merging all of the Hardware Serial code into one call implementation. Still a WIP.

I have it all as one class, where you pass in const hardware structure. This is with the exception of Serial6 on T3.6 which is LPUART class, where currently I am doing this as a sub-class...

Still want to clean this up. Things like I currently have 3 different ISR implementations. One for Serial1/2 with FIFO queues, one for the non fifo queues and third for LPUART... I had the first two as one earlier, with an if test to know if this queue is FIFO or not and branch around code... But also wondering if I can combine as currently the worker class code is marked as inline...

That is currently I have:
Code:
void uart0_status_isr(void) {
	#ifdef HAS_KINETISK_UART0_FIFO
	Serial1.status_isr_fifo();
	#else
	Serial1.status_isr();
	#endif
}
Where the code for status_isr and status_isr_FIFO are marked as inline. Wondering if it would work if I did something like:
Code:
void uart0_status_isr(void) {
	#define UART_FIFO
	Serial1.status_isr();
}
And have the implementation of status_isr, check #ifdef UART_FIFO and do the fifo stuff and if not defined not do fifo stuff... Will have to try it out.

Again WIP, so far tested on T3.6 with simple app, probably similar to what Defragster did earlier in beta code. that I output a string to Serial1, and I have a jumper for Serial1.TX to Serial2.RX, and have code that when Serial2 receives data, it sends it back out on Serial2.TX... When the last Serial port if I jumper is TX back to Serial1's RX it echoes everything it receives back in terminal window.
Code:
uint32_t current_baud = 38400;
void setup() {
  while (!Serial && (millis() < 3000)) ;
  Serial.begin(38400);
  Serial.println("Test Serial ports");
  Serial1.begin(current_baud);
  Serial2.begin(current_baud);
  Serial3.begin(current_baud);
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  Serial4.begin(current_baud);
  Serial5.begin(current_baud);
  Serial6.begin(current_baud);
#endif
}

void loop() {
  Serial.printf("Output to all Serial ports at Baud %d\n", current_baud);
  Serial1.println("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
  delay(200); // give time for it to happen

  Serial.println("Enter new baud or hit enter to continue using previous baud");

  // See if the user
  char szTemp[10];

  uint32_t new_baud = 0;
  int ch;
  while ((ch = Serial.read()) != '\n') {
    if ((ch >= '0') && (ch <= '9'))
      new_baud = new_baud * 10 + ( ch - '0');
  }
  if (new_baud && (new_baud != current_baud)) {
    current_baud = new_baud;
    Serial1.end();
    Serial2.end();
    Serial3.end();
    Serial1.begin(current_baud);
    Serial2.begin(current_baud);
    Serial3.begin(current_baud);
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Serial4.end();
    Serial5.end();
    Serial6.end();
    Serial4.begin(current_baud);
    Serial5.begin(current_baud);
    Serial6.begin(current_baud);
#endif

  }
}

void serialEvent1() {
  uint8_t buffer[80];
  uint8_t cb = min (min(sizeof(buffer), Serial1.available()), Serial.availableForWrite());
  Serial1.readBytes(buffer, cb);
  Serial.write(buffer, cb);
}

void serialEvent2() {
  uint8_t buffer[80];
  uint8_t cb = min (min(sizeof(buffer), Serial2.available()), Serial2.availableForWrite());
  Serial2.readBytes(buffer, cb);
  Serial2.write(buffer, cb);
}
void serialEvent3() {
  uint8_t buffer[80];
  uint8_t cb = min (min(sizeof(buffer), Serial3.available()), Serial3.availableForWrite());
  Serial3.readBytes(buffer, cb);
  Serial3.write(buffer, cb);
}
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
void serialEvent4() {
  uint8_t buffer[80];
  uint8_t cb = min (min(sizeof(buffer), Serial4.available()), Serial4.availableForWrite());
  Serial4.readBytes(buffer, cb);
  Serial4.write(buffer, cb);

}
void serialEvent5() {
  uint8_t buffer[80];
  uint8_t cb = min (min(sizeof(buffer), Serial5.available()), Serial5.availableForWrite());
  Serial5.readBytes(buffer, cb);
  Serial5.write(buffer, cb);
}
void serialEvent6() {
  uint8_t buffer[80];
  uint8_t cb = min (min(sizeof(buffer), Serial6.available()), Serial6.availableForWrite());
  Serial6.readBytes(buffer, cb);
  Serial6.write(buffer, cb);

}
#endif
I also added code that after it sends out the string, it waits for the user to enter something. Simple CR will send same string. If you enter a number it uses this as a new BAUD rate for all of the Serial ports...
So I tried this code out at 38400, 1000000, 2000000, 2500000 and they all appeared to work.
On my T3.6 have jumpers (1-9)(10-7)(8-31)(32-34)(33-47)(48-0)

Again WIP - Currently up at https://github.com/KurtE/cores/tree/unified-serial
I have the code that if I set a #define in HardwareSerial.h it removes the code from Serial1.c... Serial6.c HardwareSerial1.cpp... Once happy with this can remove these files and probably rename the new stuff

Also once I think this is working well, then will add in ability for addMemory... I personally am on fence on if this should be API or begin.
 
Reminds me of Processing's SerialEvent(Serial p). One question I do have is if the isr is really interrupt controlled, I looked at the code but don't really understand enough of the port manipulation/registers (still a long way off :( ). The concern I have is will this conflict with any other libraries using interrupts? Also, no sure if this would be available if I am using the TeensyThreads library where they kind of frown on using an interrupt within a thread, I am probably wrong on this. Tonton81 and tni knows a lot more about the way it works than I do. But that aside I like the approach. Is there a way to define not to use a ISR?

Thanks
Mike
 
Hi Mike,

Actually I have rarely used serialEvent in my programs, but for a test program, I thought I would put it in to make sure I did not bust things, with my reworking of all of the Serial objects. The Serial Event calls are not called during the ISR of the actual Serial code, but are called from yield(). And yield is called after each call to loop() as well as in some code that do delay loops, like delay()...

As for the Serial code using Interrupts, yes there is an ISR that is serviced for each of the Serial objects, which is the same as it is currently. I have thought of maybe changing this to not installing the ISR for all of the objects, but instead have the begin method do an attachInterruptVector, but not sure how much that would gain.

As for threads, will need to see. At some point I should play more with them and see what the state of things are. It will be interesting if Paul adds the TeensyThreads library to the install package, or waits to see where Arduino is headed with some form of threading...
 
Hi KurtE. Thanks for the explanation. Most of the time I do Serial from the main thread when using the thread library so for me its probably won't be a big impact for me - at least for now. Should try a few more things with it - another thing for the todo list.

If I wanted to play around with your fork do I have to install the whole thing? I did notice that the new stuff is from a few days to a few hours. Can I just copy them to the my current install? Maybe better I just do a clean copy with a new IDE.

Not sure Arduino folks will ever implement threading unless its for the Curie or Due type boards or other 32 bit boards. Most of what I've seen out there are really scheduling type libraries. Think that would be covered with Paul's event library which will probably be better by 10 fold.
 
Last edited:
@Paul - The version I have up on github (https://github.com/KurtE/cores/tree/unified-serial) -
I added methods to the class at least to test with,
Just tested on T3.5 with:
Where each of these buffers is 100 bytes long.
Code:
  Serial1.addStorageForRead(rxBuffer1, sizeof(rxBuffer1));
  Serial1.addStorageForWrite(txBuffer1, sizeof(txBuffer1));
  Serial2.addStorageForRead(rxBuffer2, sizeof(rxBuffer2));
  Serial2.addStorageForWrite(txBuffer2, sizeof(txBuffer2));

in slightly modified version of test app
Code:
uint32_t current_baud = 38400;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
// Optionally setup alternate pins
#define T356_ALTPINS
#endif

uint8_t rxBuffer1[100];
uint8_t txBuffer1[100];
uint8_t rxBuffer2[100];
uint8_t txBuffer2[100];

void setup() {
  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
  while (!Serial && (millis() < 3000)) ;
  Serial.begin(38400);
  Serial.println("Test Serial ports");
#ifdef T356_ALTPINS
  Serial.println("Set Alt pins for T3.5/3.6");
  Serial1.setRX(21);
  Serial1.setTX(5);
#ifdef TEST_SDCARD_PINS
  Serial2.setRX(59);
  Serial2.setTX(58);
  Serial4.setRX(63);
  Serial4.setTX(62);
#endif
#endif
  Serial1.addStorageForRead(rxBuffer1, sizeof(rxBuffer1));
  Serial1.addStorageForWrite(txBuffer1, sizeof(txBuffer1));
  Serial2.addStorageForRead(rxBuffer2, sizeof(rxBuffer2));
  Serial2.addStorageForWrite(txBuffer2, sizeof(txBuffer2));
  Serial.println("Test Serial ports");
  Serial1.begin(current_baud);
  Serial2.begin(current_baud);
  Serial3.begin(current_baud);
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  Serial4.begin(current_baud);
  Serial5.begin(current_baud);
  Serial6.begin(current_baud);
#endif
}

void loop() {
  Serial.printf("Output to all Serial ports at Baud %d\n", current_baud);
  digitalWriteFast(2, HIGH);
  Serial1.println("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
  digitalWriteFast(2, LOW);
  delay(200); // give time for it to happen

  Serial.println("Enter new baud or hit enter to continue using previous baud");

  uint32_t new_baud = 0;
  int ch;
  while ((ch = Serial.read()) != '\n') {
    if ((ch >= '0') && (ch <= '9'))
      new_baud = new_baud * 10 + ( ch - '0');
  }
  if (new_baud && (new_baud != current_baud)) {
    current_baud = new_baud;
    Serial1.end();
    Serial2.end();
    Serial3.end();
    Serial1.begin(current_baud);
    Serial2.begin(current_baud);
    Serial3.begin(current_baud);
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    Serial4.end();
    Serial5.end();
    Serial6.end();
    Serial4.begin(current_baud);
    Serial5.begin(current_baud);
    Serial6.begin(current_baud);
#endif

  }
}

void serialEvent1() {
  uint8_t buffer[80];
  uint8_t cb = min (min((int)sizeof(buffer), Serial1.available()), Serial.availableForWrite());
  Serial1.readBytes(buffer, cb);
  Serial.write(buffer, cb);
}

void serialEvent2() {
  uint8_t buffer[80];
  uint8_t cb = min (min((int)sizeof(buffer), Serial2.available()), Serial2.availableForWrite());
  Serial2.readBytes(buffer, cb);
  Serial2.write(buffer, cb);
}
void serialEvent3() {
  uint8_t buffer[80];
  uint8_t cb = min (min((int)sizeof(buffer), Serial3.available()), Serial3.availableForWrite());
  Serial3.readBytes(buffer, cb);
  Serial3.write(buffer, cb);
}
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
void serialEvent4() {
  uint8_t buffer[80];
  uint8_t cb = min (min((int)sizeof(buffer), Serial4.available()), Serial4.availableForWrite());
  Serial4.readBytes(buffer, cb);
  Serial4.write(buffer, cb);

}
void serialEvent5() {
  uint8_t buffer[80];
  uint8_t cb = min (min((int)sizeof(buffer), Serial5.available()), Serial5.availableForWrite());
  Serial5.readBytes(buffer, cb);
  Serial5.write(buffer, cb);
}
void serialEvent6() {
  uint8_t buffer[80];
  uint8_t cb = min (min((int)sizeof(buffer), Serial6.available()), Serial6.availableForWrite());
  Serial6.readBytes(buffer, cb);
  Serial6.write(buffer, cb);

}
#endif

Again the code does one Serial1.println at the beginning of loop, and then I have jumpers from Serial1->Serial2->Serial3->...->Serial6->Serial1->(writes data to )Serial I verified that the data looks correct. I also checked that the baud rates were correct...

In this test I put a set of digitalWriteFast calls around the starting println call which outputs something like 126 bytes. Without adding storage this write would wait for space to be available in the output queue to get the last bytes into it.... I then added the buffer calls and the write completes at about the time the first or second character is actually output.

Currently the main RX/TX buffers and sizes are passed into the Serial objects when they are created as to allow different sizes for each one, like before. The code would probably be slightly faster if we had one fixed size for all RX and likewise for TX, in which case the buffer could be part of the class, and then the code again compare index versus a constant instead of an instance variable, like is done in peek:
Code:
int HardwareSerial::peek(void)
{
	uint32_t head, tail;

	head = rx_buffer_head_;
	tail = rx_buffer_tail_;
	if (head == tail) return -1;
	if (++tail >= rx_buffer_total_size_) tail = 0;
	if (tail < rx_buffer_size_) {
		return rx_buffer_[tail];
	} else {
		return rx_buffer_storage_[tail-rx_buffer_size_];
	}
}

Edit: So far I have done testing on T3.6, 3.5 and TLC... Still need to run it on T3.2 and maybe 3.0

Edit2: I have now also tested on T3.2 and T3.0 which required a fix.


@mjs513 - Yes you can simply copy in the new files into your arduino installation directory, which in the case mine is at: D:\arduino-1.8.3\hardware\teensy\avr\cores\teensy3
I am actually doing all of the editing there and then I copy the changed files back into my github cores project directory.
You currently need my NHardwareSerial.(h cpp) files as well as the HardwareSerial.* files and Serial.* files.

Once I am happy and if Paul likes some of this, I will probably remove those older files and rename mine to HardwareSerial.*... But have it such that hopefully you can simply redefine one #define in the current HardwareSerial.h file and build it to use existing released code, else use the new stuff...
 
Last edited:
Paul: Saw a TeensyLoader 'file too large' warning trying to upload FrankB's Teensy64 HEX. It is a simple thing - TeensyLoader doesn't know the active MCU because it plugged in running - but complains on loading anyhow - perhaps based on last Teensy seen? Not critical if you follow through - but some folks seeing the RED FLASH of DOOM - might be put off.

I said OPEN got TOO LARGE then hit the Button and it actually talked to the Teensy and then revised its GOOD estimate – and gave the same 32% then when I said OPEN again. Here is the SPEW I got before actually flashing:
00:17:19.895: Open File event
00:18:07.564: File "c64.ino.3Aug.hex". 333472 bytes, 127% used
00:18:07.564: File contains data beyond chip size, yikes!
00:18:13.763: Verbose Info event
00:18:44.229: Device came online, code_size = 1048576
00:18:44.237: Board is: Teensy 3.6 (MK66FX1M0), version 1.03
00:18:44.316: File "c64.ino.3Aug.hex". 333472 bytes, 32% used
00:18:44.321: set background IMG_ONLINE
00:18:44.473: HID/win32: HidD_GetPreparsedData ok, device still online :)
00:19:05.016: Open File event
00:19:08.004: File "c64.ino.3Aug.hex". 333472 bytes, 32% used
 
Paul, any chance you could add a "MTP + Serial" usb mode to the next beta ?
I'd happy to test it.. and I can add it to my current project.

https://forum.pjrc.com/threads/4456...pe-in-software?p=145192&viewfull=1#post145192

EDIT: oops... there is no code in the library?
usb_mtp.c :
Code:
void usb_mtp_update(void)
{
    serial_print("test\n");

    // TODO: a lot of work here....



}

What do I have to add to be able to test it ? Is there an example anywhere ?





 
Last edited:
@KurtE Took me awhile to get to this (working another project) but I just downloaded your unified Serial branch and gave your example in your last post a shot but didn't get the string you pass to Serial1 output to serial at the end. It does ask me to change baudrates and returns and confirms it. I did notice that you changed the lib around a bit. Does the sketch above still apply?

EDIT: My issue here. Forgot I didn't solder backside pins on so I didn't have a Serial. That's what I get for assuming. Had another issue. For some reason Rx1 was not working (didn't receive anything) so I used setRX(27) for the T3.5 and reran the your sketch and everything worked as advertised. :) I will use this branch in the future. Sorry for the confusion.

Mike
 
Last edited:
Thanks Mike,

You are saying that doing Serial1.setRX(1) did not work? That would be expected. Pin 1 is TX pin for Serial1, Pin 0 is default RX pin for Serial1
 
No. After my first failure I did a serial pass through test on Serial1 by connecting pin 0 and 1 by transmitting a by Serial1.write and tried reading it back on Serial1 and it failed. All other Serial ports read, except 6 of course since it wasn't connected to begin with. To get around it I set Serail1.setRx(27) and ran the same test and it passed. In your example you had the following lines for T356:
Code:
#ifdef T356_ALTPINS
  Serial.println("Set Alt pins for T3.5/3.6");
  Serial1.setRX(21);
  Serial1.setTX(5);

I commented out setTX of course since pin1 for TX seemed to work fine (must have a bad connection some place on my breakout board), but anyway, pin 21 for the T35 didn't work so I checked the card and it showed the alternate pin for the T35/6 on pin 27 not 21. 21 didn't work for me for some reason = again have to check the connection before I say anything else.

Mike
 
Thanks Mike,
I will check up on some of these pins on some of my boards and make sure they work... It is always possible I screwed up a table of which pins are valid and the proper MUX setting...
 
I tried some of the different pins on a T3.6 and so far the Serial1 ones work:
Simple Test program:
Code:
#define XSERIAL Serial1
#define TXPIN 26 //5 
#define RXPIN 27 //21
void setup() {
  // put your setup code here, to run once:
  while (!Serial && (millis() < 3000)) ;
  Serial.begin(9600);

  #ifdef TXPIN
  XSERIAL.setTX(TXPIN);
  #endif

  #ifdef RXPIN
  XSERIAL.setRX(RXPIN);
  #endif

  XSERIAL.begin(115200);

}
uint32_t last_output;

void loop() {
  // put your main code here, to run repeatedly:
  if ((millis() - last_output) >= 1000) {
    XSERIAL.println("Test String");
    last_output = millis();
  }

  int ch;
  while ((ch = XSERIAL.read()) != -1)
    Serial.write(ch);

}
I tried it with defines for RX and TX not set so 0-1 worked, then tried 5-21, and tried 26-27.
 
KurtE. I am sure it was my set up - may have a bad solder joint based on the continuity checks. Not sure 1 and 21 didn't work though. Will be checking tonight. Working my new rover right now.

EDIT: Must have been me last night and getting wires crossed but I did test your combos as well as rx=21 and tx =1 and it all worked. I still have a problem with rx on pin 0 but that is me - 100% sure on that one.
 
Last edited:
Status
Not open for further replies.
Back
Top