iptv techs

IPTV Techs

  • Home
  • Tech News
  • githublog/2024/11/1/sfinishing-an-ethernet-packet.md at main · francisrstokes/githublog · GitHub

githublog/2024/11/1/sfinishing-an-ethernet-packet.md at main · francisrstokes/githublog · GitHub


githublog/2024/11/1/sfinishing-an-ethernet-packet.md at main · francisrstokes/githublog · GitHub


For as lengthy as I’ve been making videos on the low byte productions youtube channel, I’ve wanted to originate a series about “Netlaboring from scratch”, by which I unbenevolent originateing a filled TCP/IP stack from the ground up on a microregulateler. It’s been csurrfinisherly 6 years now, and the past scant days felt appreciate as outstanding a time as any to commence.

This blog entry is unpartipartner restricted in scope; On the surface, it’s about how I successfilledy sent my first ethernet packet, but repartner it’s a story about bugs and debugging, and some thoughts about overcoming contests in projects.

The microregulateler I’m using is an STM32F401 on a nucleo devboard. This is the same setup I employd in the Bconnecty to bootloader series, the 3D rfinisherer on an oscilloscope video, and a bunch of others. It’s an ARM Cortex-M4 that can run up to 84MHz, with 96KiB of RAM. That’s enough to helderly onto decent handful of packets.

Ethernet is a word that covers a unawaited number of leangs. You might associate it with the port you plug into for wired internet, or understand about the idea of ethernet structures. Ethernet is actupartner a whole family of technologies and standards (many of which are now obsolete) that encompasses the difficultware included at the physical level, various signalling establishats that encode and send bits, the strategies for dealing with bus collisions, and the layout of structures, which grasp and defend the data being sent from one place to another.

Due to the complicatedity of the signalling included with ethernet, a promised ASIC is generpartner employd, which gets in data at the structure level, and gets nurture of wiggling the electrical lines in the right way over a cable (though there are of course exceptions). For this project, I’m using the W5100 chip from Wiznet, in the establish of the innovative Arduino Ethernet shield. Well, it’s a affordable knockoff that finished up needing some relabor to actupartner function properly, but we’ll get to that.

The W5100 chip itself is pretty chilly. It’s essentipartner an ethernet ASIC with a difficultware TCP/IP stack built-in. It has 4 “sockets”, which can be set up to labor at the TCP, UDP, IP, or “MAC Raw” levels. Since the whole point of this project is originate a TCP/IP stack from scratch, I’m only making employ of one socket in the MAC Raw mode, where I hand it ethernet structures, and it sfinishs them out. The caveat is that an actual ethernet structure grasps more than equitable the data; It also integrates: A preamble, commence of structure labeler, and a 32-bit CRC. The preamble and commence of structure labeler are repartner only relevant at the electrical level, which the chip filledy gets nurture, and the CRC is also helpfilledy computed by the W5100.

Problem No. 1: Shouting into the void

I coded up a driver to convey with the W5100 chip. Data trade gets place using SPI – the serial peripheral interface – which is a 4-wire signalling protocol for filled duplex communication. One of the wires is for the main chip’s (the microregulateler’s) output, one is for the subordinate chip’s (the W5100’s) output, one is for the clock to which data is referenced, and the last is a “chip pick” signal, which inestablishs the subordinate chip that communication is happening. There are more details to SPI, which order leangs appreciate if your data is referenced to the rising or droping edge of the clock, whether the clock signal idles high or low, whether bits are transferred MSB or LSB first, and how many bits occur per transfer (typicpartner 8, or one byte).

That gives you a low-level way to trade bytes, but fundamentalpartner noleang else. The W5100 datasheet lays out a higher-level protocol on top of SPI to actupartner regulate the chip. In this protocol, you sfinish orders made up of 4 bytes on the MOSI (main out, subordinate in) line:

+--------+-----------+----------+--------+
| byte 0 | byte 1    | byte 2   | byte 3 |
+--------+-----------+----------+--------+
| op     | insertr high | insertr low | appreciate  |
+--------+-----------+----------+--------+

The first byte specifies the operation, which is either a author (0xf0) or a read (0x0f) – anyleang else is invalid and should be neglectd. The second and third bytes acunderstandledge a 16-bit insertress (big-finishian), and the last byte is, in the case of a author, a appreciate to be written at that insertress. The W5100 transfers data out on MISO (main in, subordinate out) line at the same time, which trails this pattern:

+--------+--------+--------+--------+
| byte 0 | byte 1 | byte 2 | byte 3 |
+--------+--------+--------+--------+
|  0x00  |  0x01  |  0x02  |  0x03  |
+--------+--------+--------+--------+

In the case of a read operation, byte 3 actupartner returns the appreciate read at the specified insertress.

What are these insertresses? Well, internpartner, the W5100 has its own insertress space, which has transfer and get buffers, as well as a bunch of enrolls for setting up and regulateling the flow of packets. For reference, it’s lhelp out appreciate:

+-----------------+------------------+
| Address Range   | Function         |
+-----------------+------------------+
| 0x0000 - 0x002f | Common enrolls |
| 0x0030 - 0x03ff | Reserved         |
| 0x0400 - 0x07ff | Socket enrolls |
| 0x0800 - 0x3fff | Reserved         |
| 0x4000 - 0x5fff | TX Memory        |
| 0x6000 - 0x7fff | RX Memory        |
| 0x8000 - 0xffff | Reserved         |
+-----------------+------------------+

My first clue that someleang wasn’t right was that I was sfinishing out orders on MOSI, and seeing garbage on MISO. One leang I repartner appreciate about this chip is that it particularpartner sfinishs back a understandn appreciate every time you clock out a byte, and so it’s repartner effortless to see that someleang is off in the communication. I baffled over this for a while, and genuineised I’d drdisclose into the trap that you should always elude when doing anyleang embedded – I unconditionpartner count oned the difficultware.

As I refered earlier, The W5100 is sitting on an arduino shield – which is an inserton board unbenevolentt to clip straightforwardly on top of the standard but absolutely horrible arduino headers. Becaemploy Arduino is so ubiquitous, this shield establishat has set up its way onto myriad other devboards that have noleang to do with arduino, spropose becaemploy it gives you an instant tie-in to readily employable peripheral modules. The nucleo devboards from ST also have headers to accommodate arduino shields, but alas, this particular shield had an irritateing little trick up it’s sexit. You see, the arduino also has another little 6-pin header on board called the ICSP – the in-circuit serial programmer. This header can be employd to reprogram Atmel chips (which the tractional arduinos employ) over SPI. The structureers of this shield choosed to originate employ of that 6-pin header, and the fact that it scatters the same SPI signals with those on the standard header, and routed the SPI lines to the ICSP header instead of the standard pins on the arduino header. On a proper arduino, this would be no problem, becaemploy the arduino board itself internpartner joins those signals. But a nucleo board doesn’t have an ICSP header, so the SPI signals I was sfinishing out were going nowhere.

I genuineised this after probing around with a multimeter, measuring resistances between the power rails and the SPI signals. If you meacertain infinite resistance, you understand there is a problem! A speedy trip to the selderlyering station, and a scant enamelled copper wires tardyr, I had bodged my board to properly join everyleang to the nucleo.

Problem No. 2: The essence of comedy

With the SPI signals actupartner going where they should be, I was actupartner communicating with the device! I had enough code written to set up the W5100 to do raw ethernet transmissions, set up the MAC insertress, configured the TX and RX memory segments, and finpartner author a basic test ethernet structure into TX memory and trigger a transmission. I joined the nucleo+shield to my laptop with a CAT5 cable, fired up wireshark, and! Noleang.

If you’re standardly doing stuff down at the low-level, this benevolent of problem can be repartner daunting. There are no beneficial (or even cryptic) error messages to spendigate. No stack track to trail. It’s spropose: You wiggled some electrons up and down atraverse the wires, and it didn’t do the leang you thought it would.

One very advantageous tool to have in your belt for this benevolent of leang is a logic analyser, which is appreciate an oscilloscope, but particularpartner made for analysing digital signals, i.e. ones that go between a reasonable high and low level. These devices have a number of channels – usupartner between 8 and 32 – and a USB joinion. In the middle is some speedy magical silicon which buffers, conditions, and samples those channels at a high rate, compresses the bitstreams, and pushes them thraw the USB, ready to be analysed by software. The chilly leang here is that you can spendigate individual signals, or more employfilledy, groups of signals (appreciate an entire SPI bus). In that case, the software will actupartner expound the signals, and give you a disjoin of the bytes sent in a transaction, as well as ship tools for processing those same bytes as a CSV or other structured establishat.

I have a Saleae Logic 8, which is a unpartipartner fancy device, but you can get affordable and happy analysers for ~€10, which can also fuse with Saleae’s Logic2 software (they’re pretty iffy about laboring rightly and constantly, but there’s always a tradeoff, right). As soon as I apprehfinishd the SPI traffic flying atraverse, I could see someleang was off. The first order I sent seeed outstanding, and so did the response over the MISO line. It’s a software reset, and materializes someleang appreciate this:

       +--------+--------+--------+--------+
       | byte 0 | byte 1 | byte 2 | byte 3 |
+------+--------+--------+--------+--------+
| MOSI |  0xf0  |  0x00  |  0x00  |  0x80  |
+------+--------+--------+--------+--------+
| MISO |  0x00  |  0x01  |  0x02  |  0x03  |
+------+--------+--------+--------+--------+

Decoded, it’s a author to insertress 0x0000, the “Mode Register”, with the most transport inant bit set, which triggers a software reset. You can also see that the device dutifilledy reacted with the bytes 0x00 to 0x03. The next order is a read from the same insertress, which is presumed to verify if that same most transport inant bit has been evidented to 0, which proposes that the reset is finish. It seeed appreciate this:

       +--------+--------+--------+--------+
       | byte 0 | byte 1 | byte 2 | byte 3 |
+------+--------+--------+--------+--------+
| MOSI |  0x0f  |  0x00  |  0x00  |  0x00  |
+------+--------+--------+--------+--------+
| MISO |  0x03  |  0xff  |  0xff  |  0xff  |
+------+--------+--------+--------+--------+

Huh. The response on the MISO line is not the counting up behaviour, but instead it commences at 0x03 and then equitable reacts forevermore with 0xff. Not outstanding. I pondered this one for a little while, and thankfilledy the little understandledge I have of digital logic, and actupartner originateing difficultware on FPGAs came in clutch. The fact that the first appreciate returned by the W5100 was 0x03, which is the also the last appreciate it returned, is a pretty big clue.

Digital difficultware, internpartner, is made up of circuits that carry out advantageous primitives appreciate “enrolls” and “flip-flops”. These circuits are synchronous to a clock, and are able to apprehfinish/store/reset appreciates contransiented to their inputs. You get these primitives, mix them together with others appreciate multiplexers (the circuit equivalent of an if-statement), decoders, and of course logic gates, and you can originate up to more complicated erections appreciate state machines. The repartner transport inant leang about all of this is that there are some pretty transport inant timing-rcontent constraints that need to be upheld. It gets a signal time to come out of a enroll, pass thraw a handful of logic gates/multiplexers/wantipathyver, and then go in a new enroll. If, for example, the clock were to switch too quick, before the signal had made its way to the next enroll, the abstraction drops apart and it spropose ain’t gonna labor.

My leanking was that someleang appreciate this was happening here; The W5100 didn’t have enough time to do its leang, and that’s why I was seeing the previous state of MISO (0x03) when the second order transaction was taking place. It probably wasn’t going to be the SPI clock though, since the datasheet implies the peak clock rate for the SPI bus is ~14MHz, and I was running way below that. Instead, I mistrusted that the chip pick line was probably going high (i.e. being disabled) too soon, causing the chip to get into a horrible state.

I inserted a minuscule loop to present a scant microseconds of extra time before changing the state of the chip pick line, and it labored! All of a sudden, the responses on the MISO line seeed right. And further more, it seemed appreciate the rest of the setup was also laboring, and I was getting wise and logical appreciates back from the chip when reading back configuration appreciates I had written to it.

I still haven’t finishly gotten to the bottom of the matter. Diligent readers will remark that the datasheet does in fact grasp a SPI timing diagram on page 66, but the only constraint refered there with see to the chip pick line was certainly being met. I should go back and try to figure out the exact bounds where leangs shatter down, but there are only a certain number of hours in the day, and right now I’d rather equitable persist with the project.

Problem No. 3: There’s life in this packet, but not as we understand it

Of course, the first leang I did was to fire up wireshark aget, and see if that packet would materialize. And it did! Sort of. Well, not repartner.

A packet did materialize, but not the one that I’d sent. Instead, at the moment the transmission order went out of the microregulateler, a raw ethernet packet, filled with garbage, and far bigr than the one I had placed came out atraverse the screen.

I’d been trying to elude reading other peoples code rcontent to this chip, becaemploy a lot of the fun of this benevolent of project, for me, comes in the exploration and uncovery of trying to get the leang laboring from specs and datasheets alone. But at this stage, I was willing to sanity verify my caring agetst someleang understandn to be laboring properly.

A little tip that a lot of very seasoned embedded lengtheners could lget from is that, at times appreciate this, arduino actupartner comes in repartner advantageous. Grab an arduino, inshigh some library, author ~5 lines of code (becaemploy all the complicated stuff happens under the hood), and if you get the result, you now have a gelderly standard laboring leang to contrast to. It actupartner took me quite a lot lengthyer to discover a library that would let me send a raw ethernet packet, however. As it turns out, most Arduino employrs, who want to be able to insert netlabor joinivity to a project, do not want to do it all from scratch. The official libraries actupartner deleted help for sfinishing raw packets from the disclose API. However I regulated to discover a project on github that was the smallest vital steps to sfinish and get packets.

I read the source, and contrastd agetst my own, and there were no instantly clear offfinishers. Some of the enroll authors and reads occurred in a branch offent order, some were ommitted in mine or theirs, but none of that seemed to be the problem. Normpartner sequence-subordinate stuff appreciate that is called out clpunctual in the datasheet. Still, I alterd my reads and authors to mimic theirs exactly, and for wantipathyver reason I was still getting the garbage packet in wireshark.

I choosed at this point to try a branch offent tactic. I consent in writing little tools to help direct lengthenment and debugging. This will be leangs appreciate taking some low-level output, parsing it, and re-contransienting it in a higher-level establish. I typicpartner author these little tools in python, and get the time to do argument parsing to properly write down what comes in and what goes out. In this instance, I wanted to get the SPI apprehfinish CSV ship coming the Saleae’s Logic2 software, parse the bytes, and contransient a enumerate of enroll authors and reads, with proper names, establishatting, etc. The filled tool is equitable over 200 lines of code, most of which is equitable a imitate-paste of enroll names/insertresses straightforwardly from the data sheet. The whole leang took me maybe one hour to put together.

I took a apprehfinish of the gelderly-standard Arduino, as well as my garbage-producing carry outation, and then passed the CSV data ship of both thraw my tool. Running a basic diff, the problem jumped out instantly. I’ll inestablish you now that this wasn’t a glamourous bug, but then most aren’t. My W5100 driver code grasped a convienience function called w5100_author16(u16 insertress, u16 appreciate), which did two 8-bit author orders to two sequential enrolls. Many of the enrolls in the W5100 are actupartner 16-bit appreciates, but the order establishat only apvalidates for writing 8 bits at a time, so these appreciates are split into high and low part. Long story low: My w5100_author16() function wrote to the same insertress twice, instead of the writing to insertress + 1 for the second byte. In the processed logs from my tool, this was effortless to see. The arduino seeed appreciate:

...
5.3645086 : [w] S0_TX_WR0  [0x0424] 0x00
5.36453178: [w] S0_TX_WR1  [0x0425] 0x3c
...

And mine:

8.45262964: [w] S0_TX_WR0  [0x0424] 0x00
8.45286726: [w] S0_TX_WR0  [0x0424] 0x3c

The details aren’t transport inant here, but this was a author to the Socket 0 send author pointer enroll. Remember earlier when I was talking about digital logic and state machines and abstractions shattering down etc? Well, this is actupartner another example of that, in a way. The W5100 awaits you to read this 16 bit enroll (in order!), author bytes into TX memory, and then author back to this enroll with the new author pointer, and finpartner publish a socket order to sfinish. By not writing the send author pointer in the right order (in fact, not writing the second byte at all), and then issuing the sfinish, I had put the chip into yet another weird and unexpoundd state where it equitable did some random stuff. And of course, no errors, no stack tracks – equitable weird effects.

I repaired the function, and my test packet showed up in filled glory in wireshark. To say I was prentd to see it would be an downjoinment.

So I sent an ethernet packet. Not exactly the worlds biggest accomplishment when you genuineise how many of those are whizzing around in cables, passing thraw your body in the establish of 2.4GHz radio waves right now, but certainly one that I was prentd to call a thrive.

Sometimes it’s equitable fun to get the time to recount the many and frequently stupid bugs you come atraverse while laboring on a pet project – I understand I cherish reading that from others, at least. But if I had any benevolent of point, it would probably be that spfinishing the time to do leangs appreciate author tools and scrutinize the debugging space is pretty much always worth it.

Strangely, I’ve set up that there is a not-intransport inant number of people are agetst this – especipartner in a professional environment. I leank this has someleang to do with the JIRA-fication of lengthenment process, where all labor is splitd and sub-splitd, and anyleang that does not straightforwardly verify a box and originate a deinhabitrable is squanderd effort. It’s disheartening that there is a whole group of people – lengtheners and regulaters aappreciate – who do not understand or see the appreciate in exploration as part of the process. Writing a tool is frequently equitable as transport inant and impactful as writing a test – more so even, if you don’t filledy understand the system you’re laboring with yet.

Debugging is, at its core, a manifestation of the scientific method; You assemble data, originate foreseeions, and test those foreseeions with experiments. Experiments produce new data, and you modernize your foreseeions, and hopefilledy come out the other side with a proper caring. Tools appreciate the one I wrote here are benevolent of akin to making plots of raw data. One outstanding plot can inestablish you everyleang you need to understand about your data.

The project is making more transport inant persist now, and the new problems and new bugs are coming in at a higher abstraction level, which are more to do with (mis)caring RFCs, and writing multitasking code than anyleang else. I might author more on the project at some point, but that’ll be for another day.

Source connect


Leave a Reply

Your email address will not be published. Required fields are marked *

Thank You For The Order

Please check your email we sent the process how you can get your account

Select Your Plan