Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

acm problems #2

Open
aMOPel opened this issue Jun 16, 2022 · 3 comments
Open

acm problems #2

aMOPel opened this issue Jun 16, 2022 · 3 comments

Comments

@aMOPel
Copy link

aMOPel commented Jun 16, 2022

Hi again,

I've been playing around with the migen acm example on the fomu for a bit now.
While testing the connection and it's limits I've come across problems I can't seem to solve.
Probably it's related to me operating the acm module incorrectly.
If you could help me or point me a good direction it would be very appreciated.

The test works like this:

  • On the fomu, send bytes from 0x00 - 0xff over acm
  • On the host, read 256 bytes and check if it's really 0x00 - 0xff
  • repeat

This is how I am currently operating the NitroMuAcmBuffered module:

        self.START_CHAR = ord('b') # after receiving this char, start sending
        self.END_CHAR = ord('e') # after receiving this char, stop sending

        self.comb += [
            muacm.in_last.eq(0),
            muacm.out_ready.eq(1),
            muacm.in_flush_time.eq(0),
        ]

        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm

        FRAME_SIZE_BITS = 8
        counter = Signal(FRAME_SIZE_BITS)

        fsm.act(
            "IDLE",
            red_pwm.eq(0),
            green_pwm.eq(1),
            blue_pwm.eq(0),
            NextValue(counter, 0),
            NextValue(muacm.in_data, 0),
            NextValue(muacm.in_valid, 0),
            NextValue(muacm.in_flush_now, 1),
            If(
                muacm.out_data == self.START_CHAR,
                NextState("SENDING"),
            ),
        )

        fsm.act(
            "SENDING",
            red_pwm.eq(0),
            green_pwm.eq(0),
            blue_pwm.eq(1),
            NextValue(muacm.in_flush_now, 0),
            If(
                muacm.out_data == self.END_CHAR,
                NextValue(counter, 0),
                NextValue(muacm.in_data, 0),
                NextValue(muacm.in_valid, 0),
                NextState("IDLE"),
            ).Elif(
                muacm.in_ready,
                NextValue(counter, counter+1),
                NextValue(muacm.in_data, counter),
                NextValue(muacm.in_valid, 1),
            ),
        )

This is my test setup using pyserial lib:

    def test_cycle(self):
        amount_bytes = 2**8
        iterations = 2000

        for j in range(iterations):
            start_trng(self.ser) # sends 'b'
            result = read_trng(self.ser, amount_bytes)
            # time.sleep(0.01)
            end_trng(self.ser) # sends 'e'

            for i, byte in enumerate(result):
                assert int(byte) == i

The resulting problems:

  1. running the test like this results in an assertion error in the 6th or 7th iteration, it varies.
  2. uncommenting the time sleep line, the test throws an assertion error always in the 25th iteration. So that's when the received bytes deviate from the expected bytes. This seems to be directly related to the amount of total sent bytes. I did a little bit of testing with a different bit size for the counter:
  • 8 bits 25 iterations with sleep(0.01)
  • 7 bits 50 iterations with sleep(0.01)
  • 6 bits 98 iterations with sleep(0.01)
  • 5 bits 196 iterations with sleep(0.01)
  1. running the test without assertion and sleep, it gets stuck after some (seemingly) random point. Sometimes after tens of iterations sometimes after hundreds. Interesting to note is that the rgb is green when it gets stuck, so it stays in the IDLE state. Probably this issue is related to timing. The message from the host to start for some reason arrives at a bad point in time and dissipates. (Maybe I shouldn't set out_ready to 1 at all times)
  2. running the test without assertion but with sleep, it runs all iterations. The delays seems to solve the timing issue from 3.. But as mentioned in 2. after some point the counter and the acm buffer go out of sync at iteration 25. Interestingly the output stays the same for 26 until the end. This behaviour stays the same on repeated executions of the test.
    Iteration 0 - 24
\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;
<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\
x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\x
ba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe
0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff

Iteration 25

\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;
<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x1
0\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxy
z

Iteration 25 - end

{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa
3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9
\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\
xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17
\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz

So my conclusion from all this testing is that there are 2 problems.

  1. I am not handling messages from the host properly and need to enable out_ready only at certain times. I tried, but couldn't figure it out.
  2. Something happens somewhere in the usb connection stack that causes trouble after a certain amount of consecutively sent bytes. Maybe some buffer runs full the first time and this throws things off a bit.
@smunaut
Copy link
Member

smunaut commented Jun 16, 2022

Could you post the whole code somewhere so I could try it locally on a FOMU ?

@aMOPel
Copy link
Author

aMOPel commented Jun 16, 2022

https://github.com/aMOPel/fomu-trng/tree/try_all_comb/src

The majority of the code is taken from your migen_icebreaker_muacm.py

@aMOPel
Copy link
Author

aMOPel commented Jun 16, 2022

I was trying enabling out_ready only at certain points but it didn't change anything. It's quite possible pyserial is by not making use of the valid and ready signals and I need to enable it in the configuration.
There are different flow control settings it can use. I didn't figure out which is the right one for acm if any yet, though.
https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.xonxoff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants