Teensyduino 1.54 Beta #9

Status
Not open for further replies.
Yes sending from Serial2 to Serial1 via the proper TX->RX etc.

I wasn't trying to measure the delay. Just reporting that the flush() function wasn't working with the string I was sending. I was also reporting that if I put a delayMicroseconds(75) after the flush all the characters would be available for read().

However, that is not how flush() is supposed to work. With flush() I'm not supposed to have to add a delay in there. So I was reporting a bug in when flush() returns in this case.

The other comment about the FIFO makes sense with the fact that a longer string does come through properly. Without looking at the code there may be a case where flush() returns as long as the entire string can fit into the FIFO but before they are actually all sent.

However, it doesn't seem related to the read() side of things because only changing from printf() to println() changes the behavior.
 
Here is a quick and dirty version of your sketch. Note: I did include Serial1 here....
Code:
void setup() {
  pinMode(2, OUTPUT);
  digitalWriteFast(2, LOW);
  pinMode(3, OUTPUT);
  Serial2.begin(115200);
}
void loop() {
  digitalWriteFast(2, HIGH);
  Serial2.printf("ID 0 1\n");   // this doesn't work
  digitalToggleFast(3);
  Serial2.flush();
  digitalWriteFast(2, LOW);
  delayMicroseconds(100);
  digitalWriteFast(2, HIGH);
  Serial2.println("ID 0 1");       // this works
  digitalToggleFast(3);
  Serial2.flush();
  digitalWriteFast(2, LOW);
  delay(50);
}
Note Your posting did not include a complete program, which included setup, so I just choose 115200 as the baud rate...

Here is a quick and dirty capture of the output showing the effects of the flush...
I did a toggle after each output to be different which shows when the Serial.print like command actually completed. And I did High/Low around the Serial data where it went low after the flush returned...
Screenshot 2021-05-25 083356.jpg
 
So why was Serial1.available() not catching all the characters from the printf case? Is it slower? Faster? Was it a logic race on pulling them out of the receive FIFO before available() reports empty?

Why did println() work and printf() not work on exactly the same string and the same code on the receive side?

You didn't include the reception by Serial1 of the transmission from Serial2. That was the key problem. I know it is an odd case but loopback is a valid function that should work.
 
So why was Serial1.available() not catching all the characters from the printf case? Is it slower? Faster? Was it a logic race on pulling them out of the receive FIFO before available() reports empty?

Why did println() work and printf() not work on exactly the same string and the same code on the receive side?

You didn't include the reception by Serial1 of the transmission from Serial2. That was the key problem. I know it is an odd case but loopback is a valid function that should work.

It is but is not instantaneous. Again the first test was to show that Serial.flush2() is working properly.

Again what is happening between your two lines has very little to do with printf versus println here.
What it has to do is the printf is outputing 7 bytes and the println is outputting 8 (that is printlin outputs a trailing \r\n

So I mucked up the Serial1 ISR to show when the ISR is called and the line above I toggled an IO pin each time I receive a character:

Code:
void setup() {
  pinMode(2, OUTPUT);
  digitalWriteFast(2, LOW);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  Serial2.begin(115200);
  Serial1.begin(115200);
}

void loop() {
  digitalWriteFast(2, HIGH);
  Serial.print("printf: ");
  Serial2.printf("ID 0 1\n");   // this doesn't work
  digitalToggleFast(3);
  Serial2.flush();
  digitalWriteFast(2, LOW);
  int count_read_remaining = 7;
  elapsedMicros em = 0;
  while (count_read_remaining) {
    while(!Serial1.available());
    Serial.write(Serial1.read());
    digitalToggleFast(4);
    count_read_remaining--;
  }
  Serial.printf(" - em: %u\n", (uint32_t)em);
  delayMicroseconds(100);
  digitalWriteFast(2, HIGH);
  Serial.print("printf: ");
  Serial2.println("ID 0 1");       // this works
  digitalToggleFast(3);
  Serial2.flush();
  digitalWriteFast(2, LOW);
  count_read_remaining = 8;
  em = 0;
  while (count_read_remaining) {
    while(!Serial1.available());
    Serial.write(Serial1.read());
    digitalToggleFast(4);
    count_read_remaining--;
  }
  Serial.printf(" - em: %u\n", (uint32_t)em);
  delay(250);
}
What is interesting is:
In the shorter case the hardware awaits a specific time for for the next character to be received or until the watermark value in hardware has been reached...
You can see difference in timing while waiting:
Code:
printf: ID 0 1
 - em: 95
printf: ID 0 1
 - em: 23
printf: ID 0 1
 - em: 95
printf: ID 0 1
 - em: 23
printf: ID 0 1
 - em: 95

screenshot.jpg

Note: In T4 code base the wait was much longer (one full character timing), and I added code to it that when you asked for available and read it would reach into hardware FIFO and grab the data if necessary.
 
Very interesting analysis but the fact remains that flush() should not return until all of the characters have cleared the hardware transmitter.

Similarly available() should not return false if characters are in the FIFO but not in the RAM buffer yet.
 
UdpNtpClient issue with Teensyduino 1.54 Beta #9

I install the clean copy of Teensyduino 1.54 Beta #9 over Arduino 1.8.15 and tried UdpNtpClient.
I had some issues with dns with Teensyduino 1.53 so I decided to try 1.54 Beta #9.
Now dns is not working at all. Below is the capture from my pfsense box.
The dns DNSClient::fnet_dns_callback returns addr_list_size = 0

23:08:28.108870 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 51, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49161 > 192.168.1.254.53: [udp sum ok] 9474+ A? time.nist.gov. (31)
23:08:28.108902 00:01:29:98:35:07 > 00:e0:97:00:01:03, ethertype IPv4 (0x0800), length 112: (tos 0x0, ttl 64, id 33767, offset 0, flags [none], proto UDP (17), length 98)
192.168.1.254.53 > 192.168.1.136.49161: [bad udp cksum 0x8536 -> 0x5aec!] 9474 q: A? time.nist.gov. 2/0/0 time.nist.gov. CNAME ntp1.glb.nist.gov., ntp1.glb.nist.gov. A 132.163.97.1 (70)
23:08:29.110901 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 52, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49161 > 192.168.1.254.53: [udp sum ok] 9474 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:30.112913 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 53, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49161 > 192.168.1.254.53: [udp sum ok] 9474 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:31.114930 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 54, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49161 > 192.168.1.254.53: [udp sum ok] 9474 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:32.116946 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 55, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49161 > 192.168.1.254.53: [udp sum ok] 9474 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:33.118960 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 56, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49161 > 192.168.1.254.53: [udp sum ok] 9474 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:45.122145 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 57, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49162 > 192.168.1.254.53: [udp sum ok] 33002+ A? time.nist.gov. (31)
23:08:45.171204 00:01:29:98:35:07 > 00:e0:97:00:01:03, ethertype IPv4 (0x0800), length 112: (tos 0x0, ttl 64, id 1412, offset 0, flags [none], proto UDP (17), length 98)
192.168.1.254.53 > 192.168.1.136.49162: [bad udp cksum 0x8536 -> 0x0ff0!] 33002 q: A? time.nist.gov. 2/0/0 time.nist.gov. CNAME ntp1.glb.nist.gov., ntp1.glb.nist.gov. A 132.163.97.3 (70)
23:08:46.124151 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 58, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49162 > 192.168.1.254.53: [udp sum ok] 33002 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:47.126165 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 59, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49162 > 192.168.1.254.53: [udp sum ok] 33002 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:48.128180 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 60, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49162 > 192.168.1.254.53: [udp sum ok] 33002 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:49.130196 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 61, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49162 > 192.168.1.254.53: [udp sum ok] 33002 q: A? time.nist.gov. 2/0/0 [|domain]
23:08:50.132196 00:e0:97:00:01:03 > 00:01:29:98:35:07, ethertype IPv4 (0x0800), length 73: (tos 0x0, ttl 64, id 62, offset 0, flags [none], proto UDP (17), length 59)
192.168.1.136.49162 > 192.168.1.254.53: [udp sum ok] 33002 q: A? time.nist.gov. 2/0/0 [|domain]
 
@Paul: Would you merge a PR that adjusts Audio SAMPLE_RATE for USB-audio automatically (or at least for 48k)?

I really need 48k (and I guess some others, too) ... for usb audio.
If you want to add audio-support for the USB - Host, 48k would be useful, too.

Edit: I was unclear. I want to adjust the Audio USB settings to the used samplerate only.
 
Last edited:
The dns DNSClient::fnet_dns_callback returns addr_list_size = 0

In my experience (and others, who took this issue up with the FNET author), the DNS lookup code in NativeEthernet/FNET will not return a host IP if the lookup is done on an alias (CNAME). To establish the IP address, the FNET code compares the hostnames returned from the DNS inquiry with the original inquiry hostname, so it will never match in the case of an alias.

time.nist.gov is an alias; replace the timeServer name in UdpNtpClient to the underlying aliased hostname, and try it:

Code:
const char timeServer[] = "ntp1.glb.nist.gov";

As a temporary hack to enable use of aliased hosts - I didn't have time to research the appropriate solution - I removed the if condition (not the code it executes, just the condition) in fnet_dsc.c around line 445:

Code:
                                [COLOR="#0000FF"]//Comment out the if statement in the next line[/COLOR]
                                //if(_fnet_dns_cmp_name(rr_name, dns_if->host_name) == FNET_TRUE)
                                {
                                   /* Check Question Type, Class and Resource Data Length. */
                                    if ( (rr_header->type ==  dns_if->dns_type) &&
                                        (rr_header->rr_class == FNET_HTONS(FNET_DNS_HEADER_CLASS_IN)))
                                    {
                                        /* Resolved.*/
                                        if(rr_header->type == FNET_HTONS(FNET_DNS_TYPE_A))
                                        {
                                            dns_if->resolved_addr[dns_if->addr_number].resolved_addr.sa_family = AF_INET;
                                            ((struct fnet_sockaddr_in *)(&dns_if->resolved_addr[dns_if->addr_number].resolved_addr))->sin_addr.s_addr = *((fnet_ip4_addr_t *)(ptr+sizeof(fnet_dns_rr_header_t)));
                                        }
                                        else /* AF_INET6 */
                                        {
                                            dns_if->resolved_addr[dns_if->addr_number].resolved_addr.sa_family = AF_INET6;
                                            FNET_IP6_ADDR_COPY((fnet_ip6_addr_t *)(ptr+sizeof(fnet_dns_rr_header_t)), &((struct fnet_sockaddr_in6 *)(&dns_if->resolved_addr[dns_if->addr_number].resolved_addr))->sin6_addr.s6_addr);
                                        }
                                        dns_if->resolved_addr[dns_if->addr_number].resolved_addr_ttl = rr_header->ttl;
                                    
                                        dns_if->addr_number++;
                                        if(dns_if->addr_number >= (FNET_CFG_DNS_RESOLVED_ADDR_MAX)) /* Check address number limit */
                                        {
                                            break;
                                        }
                                    }

                                }

This is not a final solution; it is a workaround. The FNET author believes this code is correct; NativeEthernet for now appears unsupported (no activity on the forum or in the codebase for several months), which is a shame, because it's super useful, apart from a couple of minor issues like this. So, I'll live with this workaround for my limited use cases.
 
Is there a version for macOS Big Sur 11.4 ?

I am currently using long time a go installed 1.53 and having some hangs on UI, like when accessing files. also now some weird issues with micros() a the code timing was not working and printing the micros() showed that 3 last numbers where always 000? Older version of the same code worked though and uses also micros(). This was with Teensy 4.0. Also is there any hope for better i2c for Teensy 4.0 than Wire?

Anyway, feels it is time to reinstall, but what should I instal to Big Sur?
 
In post #1 this:
MacOS 10.10 to 10.15:
com/teensy/td_154-b...S_Catalina.zip

Should work if it is built like the current release version

Macintosh Installation
Download Teensyduino for MacOS 10.10 - 11.x.
Note: This download is a complete copy of all software. No separate installer is used.
On first use, you must allow access to your Documents folder.
 
Thanks, I uninstalled Java and reinstalled, and now the hangs at least when accessing file seems to be gone.

But any idea how micros() could break like that? I do not see how that could be Java related. it has felt like the .ide gets somehow corrupted, opening older version of the code and redoing same changes and it works. I think I onece had problem also with delayMicroseconds() but that could have been something else also.
 
Thanks, I uninstalled Java and reinstalled, and now the hangs at least when accessing file seems to be gone.

But any idea how micros() could break like that? I do not see how that could be Java related. it has felt like the .ide gets somehow corrupted, opening older version of the code and redoing same changes and it works. I think I onece had problem also with delayMicroseconds() but that could have been something else also.

Not seeing context for "how micros() could break like that" ?

If there is a repro example - putting it on a thread might get to an explanation of any problem
 
This problem feels it is not my code or even libraries, but something under them. The code needs i2c IMU to run. Also as said the same code edited again from older version works fine. So it is very weird. I am using now ARM_DWT_CYCCNT to time.

The colourful spinning feel is back when accessing file, that makes the CPU temperature to hit 96 degrees C in few seconds ? :(

I think it is related to the serial monitor, to test I do short periods 6000 lines per second. Something gets bufferend and that affects accessing the file even after serial monitor is closed.


Overall I think the serial monitor and serial plotter tries to print too fast, there is no reason to try to update the display faster than the display is updated, in my case 60 FPS. i.e in this case 100 lines should be updated per every frame and that should not load the CPU. Also as the line is maybe 100 bytes, les than 1Mb per secon buffer filling should not cause any loading on modern computers. (but I can keep serial plotter open only for short times or the macBook Pro tries to take off with its fans running full speed.)

The micros() problem could be related also to Wire.h. I was polling the sensor as fast as possible. no that is fixed, done differently. Also the i2c loading is heavy, the sensor supports only 400k rate but could provide 14 bytes 4kHz, so it does not fit and trying to read two sensors at same time on same i2c. The sensor seems however to work at 1M i2c rate.
 
Last edited:
This problem feels it is not my code or even libraries, but something under them. The code needs i2c IMU to run. Also as said the same code edited again from older version works fine. So it is very weird. I am using now ARM_DWT_CYCCNT to time.

...

Indeed the SerMon gets over whelmed by fast output - and that causes problems. Best to have the sketch limit what is sent, or problems can be expected. There is a T_3.6 feeding 2 DACs data of a sine wave to a T_4.0 for ADC reads on desk just now where that was done to allow the plotter to visualize it and been running for days.

Something with micros() seems a topic worthy of a thread as it doesn't seem to be a problem from the current beta as micros() or other seeming related hasn't changed in the PJRC TD code.

IMU may be something others have to repro the issue - or the problem may show just seeing the code. The _CYCCNT is something enabled on T_4.x and used to track micros and needs to be treated as a read only value and not changed in user code.
 
After some more investigation this morning with fresh eyes, found the problem, and it is on my code. The strange thing though is sometimes this fails, and with the same problem the millis() may work ok also.

On this code I have taken away about everything else than the failing part.

Code:
        enum { x, y, z, t };
        int16_t accRAW[3][4]; //x, y, z


        uint32_t synchTime; 
        uint32_t SPS;
        bool     RequestNew1;
        bool     RequestNew2;
       
    void setup() {
            
  
      

    }

    void loop() {

           RequestNew1 = false;RequestNew2 = false;
         
         if( RequestNew1 == false &&  RequestNew2 == false ){
            
  

            accRAW[t][0] =  0xF0FF;  



            //debug print
            delay(1);//added so that delay should be at least 1 ms i.e SPS 1000
            SPS = (1000000/(micros()-synchTime));
            synchTime = micros();
            Serial.print(SPS); Serial.print("\t");
           
           
            Serial.println(); 

            
         } 

          
    }

The problem is

enum { x, y, z, t };
int16_t accRAW[3][4]; //x, y, z
so accRAW[t][0] = writes outside the array.

this causes the micros() to fail miserably

commenting out accRAW[t][0] = 0xF0FF; and the SPS is 999 as it should, without comenting it is often 0 but randomly something else.

The strange thing is, on the current version of the code I am working with, there is the same mistake, but not causing problems.
 
" Best to have the sketch limit what is sent, or problems can be expected."

The thing is, I need to see all samples to see they are correctly sampled and no jitter. I really hope the serial plotter and monitor performance would be what could be expected 2021, With 6 core i7 16 g memory it really is not the computer HW limiting the performance on something like this.
 
"that is why it's called undefined behavior " yes I guess so :)

but wonder, for the compiler it should be easy to see something gets written outside the limits. Why does it let to compile this?
 
" Best to have the sketch limit what is sent, or problems can be expected."

The thing is, I need to see all samples to see they are correctly sampled and no jitter. I really hope the serial plotter and monitor performance would be what could be expected 2021, With 6 core i7 16 g memory it really is not the computer HW limiting the performance on something like this.

Indeed the Teensy 4.x USB at 400 Mbps seems to easily overwhelm the buffer handling of a PC when unconstrained. Paul worked long and hard to get the Teensy Ports to be as good as it is and much better than the IDE's pure JAVA SerMon - but that code still handles the Plotting case. And when his 'week' of optimizing was done it just found that the buffer data managed by the OS was not 'clean and in order'. It is puzzling given the other methods through Serial can handle faster data safely from external drives. Linux was found to be a bit better than Windows or Mac - but ill formed or out of orders buffers happen.

The Teensy often has enough cycles to 'validate' data as it prints - when the cycles are available and the data can be 'categorized' for the expected.
> For instance the SINE wave example the T_3.6 is sending the two DAC value 180° out of phase - so the T_4.0 sketch simply adds them and expects to see the sum as 3.30 or 3.31 volts as presented from the ADC read after conversion.
Using TyCommander and Dual Serial USB with the IDE Plotter running on the SINE plot at slow speed - there is then the second Serial Monitor port for TyCommander to print status and any anomalies
 
"that is why it's called undefined behavior " yes I guess so :)

but wonder, for the compiler it should be easy to see something gets written outside the limits. Why does it let to compile this?

Seems it is not built to track 'enum' values. Does it warn with :: enum { x=0, y, z, t }; or enum { x, y, z, t=3 };
 
With LabView I can easily make what ever plotting, the problem just is I only have that on Windows and I am done with Windows unless I absolutely need to go there (and when I do it always takes hours for the updates to be done).

But as the Arduino serial monitor and plotter are so limited on data handling, and if no hope getting them better, is there better alternatives for macOS?
 
but wonder, for the compiler it should be easy to see something gets written outside the limits. Why does it let to compile this?


C/C++ has zero validation of array indexes (or indeed pointers in general). That is what makes the language so fast and versatile compared to other languages like java and python that do.
 
C/C++ has zero validation of array indexes (or indeed pointers in general). That is what makes the language so fast and versatile compared to other languages like java and python that do.

Well maybe it would be time to have an option on compiler to validate them...

one would not need to run that every time, but when problems if would be super useful and time saving tool.

I spend hole yesterday with that stupid problem. and it was not that I did not look or think about it in here

enum { x, y, z, t };
int16_t accRAW[3][4]; //x, y, z
int16_t gyroRAW[4][4];//x, y, z, temp

the problem was I did not notice temp was part of acc, not gyro (now it is separate)
 
C/C++ has zero validation of array indexes (or indeed pointers in general). That is what makes the language so fast and versatile compared to other languages like java and python that do.

The compiler will check and warn for 'obvious' errors:
This code shows warnings below - does not do the same catch on the enum:
Code:
enum { D, y, z, t, Q=4 };
uint32_t foo[4];
uint32_t foo2[4][4];

void setup(void) {
  foo[4]=1;
  foo2[4][3]=1;
  foo[Q]=1;
  foo2[4][t]=1;


Code:
T:\tCode\T4.1LIS3DH-HardwareSPI-SDcard\T4.1LIS3DH-HardwareSPI-SDcard.ino: In function 'void setup()':
T:\tCode\T4.1LIS3DH-HardwareSPI-SDcard\T4.1LIS3DH-HardwareSPI-SDcard.ino:34:8: warning: array subscript is above array bounds [-Warray-bounds]
   foo[4]=1;
        ^
T:\tCode\T4.1LIS3DH-HardwareSPI-SDcard\T4.1LIS3DH-HardwareSPI-SDcard.ino:35:9: warning: array subscript is above array bounds [-Warray-bounds]
   foo2[4][3]=1;
         ^
 
Status
Not open for further replies.
Back
Top