Skip to content
This repository has been archived by the owner on Jul 6, 2019. It is now read-only.

Platform Tree parser documentation

Vladimir Pouzanov edited this page Jul 15, 2014 · 3 revisions

Here's how PT generation for platformtree!() macro works.

  1. Parser converts the token stream to node::PlatformTree object. node::PlatformTree contains all the nodes for the PT and an additional name-based index.
  2. node::PlatformTree is passed to Builder::build().
  3. Builder verifies that top-level nodes are mcu, os and drivers.
  4. Builder calls attach for mcu node first.
  5. attach function finds the actual attach implementation for mcu based on the node name and forwards the call, or sets the materializer to one that generates error.
  6. Builder calls attach for os and drivers.
  7. Builder walks over all the nodes in the order of appearance and calls mutators if they are present.
  8. Builder walks over all the dependencies of mcu::clock and calls materializers.

Now, the process specifically for lpc17xx mcu. What happens in materializers.

For each child node in mcu, attach sets the dependency (so that mcu node depends on child nodes) and calls the corresponding materializer.

  1. attach for clock just binds the materializer. mcu::clock is the primary node that always must be present in PT, everything else depends on it.
  2. When called, materializer for clock verifies node arguments, and resolves all the required values.
  3. It must verify that the clock config is reasonable (this code is missing).
  4. It modifies the node by providing system_frequency attribute. Other nodes can use it to figure out the system clock.
  5. Next it generates the code item that will be part of the main function. quote_expr!() helps a lot in here. Note that you should use simple data structures here and make sure that they get inlined. Use common rust pattern of new functions. Try to do all validations in here and skip them in runtime part of the code. Runtime code must be marked as unsafe then.
  6. Back from clock, we're moving on to timer. It has a trivial materializer that just verifies the correctness of root timer node, actual work is node in subnodes.
  7. Timer node emits an usable item — the instance of a timer. To do that it first sets the item type name, which must be full-qualified.
  8. It uses a let statement to create a local variable. Using node name for variable name is always safe.
  9. Next, UART node. UART depends on rx and tx pins but also needs to set those pins up before they are materialized. It uses a mutator for that. Note that it still resolves all other dependencies.
  10. When mutator is called, it sets up pin direction and function attributes. That's why there's no need to configure those pins in PT source.

TODO: write about how os node is materialized.