I"m using asn1 and the asn1scc compiler -
https://github.com/ttsiodras/asn1scc on a project atm. It has been working well for me. ASN1SCC is an embedded friendly compiler, its used by the ESA for spacecraft. I played with a few other ASN compiler that I would pick if it wasn't an embedded project, I don't remember which.
It generates parsers that don't need heap and have worst case size constants for packing and unpacking so you can statically allocate the space if you want/need to. Downside is you can't have unbounded variable length arrays (bounded variable length is ok though, but it will increase the size it reserves for decoding!) and some of the fancier built in types. It also can generate XER encoding code, which is nice, actually. On the laptop I can export to XML, edit a config file, and recompile to BER for transfer to the embedded target. I have 2 little 20 line c++ programs to handle generate default blob -> xml -> ber and ber -> xml.
I've also use google protobuf a lot server side, and there is supposed to be a embedded library called nanopb
https://github.com/nanopb/nanopb, although I haven't tried it. Protobuf is a little too happy with dynamic memory for me now (working on a soft real time system, for general use its fine).
I liked that ASN.1 lets me be way more explicit about what the valid ranges for integers are, a big win over protobuf. I have fields that take several disjoint ranges of values, easy. Like INTEGER(0 .. 51 | 554 | 8889 .. 9999) is legal and enforced by the decoder. Its nice when you need to be specific...