Recovering public key with small R parameter I use for tests small toy 16-bit elliptic curve:
Modulus prime p: 65167
a:       0
b:       7
order:   64879
G:      (62171,14828)

(generated by brichard19/ecdl on Github)
I use procedures:
bool Ecdsa16::sign_simple(const uint16_t privateKey, const uint16_t msgHash, const uint16_t nonce, uint16_t &amp;outR, uint16_t &amp;outS) {
    if (nonce==0 || nonce&gt;=CurvePoint16::ORDER) return false;
    CurvePoint16 p = CurvePoint16::G;
    p = CurvePoint16::privateExponentToPublicPoint(nonce);
    uint16_t r = p.x.value % CurvePoint16::ORDER;
    if (r == 0) return false;
    outR = r;
    uint16_t s = (int64_t)reciproc(nonce, CurvePoint16::ORDER) * (msgHash + (int64_t)r * privateKey) % CurvePoint16::ORDER;
    if (s == 0) return false;
    s = std::min((int)s, CurvePoint16::ORDER - s);
    outS = s;
    return true;
}

bool Ecdsa16::verify_simple(const CurvePoint16 &amp;publicKey, const uint16_t msgHash, const uint16_t r, const uint16_t s) {
    if (publicKey == CurvePoint16::ZERO || !(publicKey.z.value==1) ||
        !(publicKey.x*publicKey.x*publicKey.x+FieldInt16(7)==publicKey.y*publicKey.y))
        return false;
    CurvePoint16 checkzero = publicKey;
    checkzero.multiply(CurvePoint16::ORDER);
    if (checkzero!=CurvePoint16::ZERO) return false;
    if (!(0 &lt; r &amp;&amp; r &lt; CurvePoint16::ORDER))  return false;
    if (!(0 &lt; s &amp;&amp; s &lt; CurvePoint16::ORDER))  return false;
    uint16_t  w = reciproc(s, CurvePoint16::ORDER) % CurvePoint16::ORDER;
    uint16_t u1 = ((uint32_t)msgHash * w) % CurvePoint16::ORDER;
    uint16_t u2 = ((uint32_t)r * w) % CurvePoint16::ORDER;
    CurvePoint16 p = CurvePoint16::G;
    CurvePoint16 q = publicKey;
    p.multiply(u1);
    q.multiply(u2);
    p.add(q);
    p.normalize();
    return r == p.x.value % CurvePoint16::ORDER;
}

bool Ecdsa16::recovery(const uint16_t msgHash, const uint16_t r, const uint16_t s, CurvePoint16 &amp;publicKeyA, CurvePoint16 &amp;publicKeyB) {
    const uint16_t &amp;order = CurvePoint16::ORDER;
    const uint16_t &amp;zero = 0;
    if (!(zero &lt; r &amp;&amp; r &lt; order &amp;&amp; zero &lt; s &amp;&amp; s &lt; order))
        return false;
    FieldInt16 rf(r);
    CurvePoint16 R1(rf);
    CurvePoint16 R2 = R1;
    R2.negate();
    uint16_t rinv = reciproc(r, CurvePoint16::ORDER);
    uint16_t negmsg;
    negmsg = CurvePoint16::ORDER - msgHash;
    if (msgHash&gt;=CurvePoint16::ORDER)
        negmsg+=CurvePoint16::ORDER;
    uint16_t u1 = ((uint32_t)negmsg * rinv) % CurvePoint16::ORDER;
    uint16_t u2 = ((uint32_t)s * rinv) % CurvePoint16::ORDER;
    CurvePoint16 u1G = CurvePoint16::G;
    u1G.multiply(u1);
    CurvePoint16 u2R1 = R1;
    u2R1.multiply(u2);
    CurvePoint16 u2R2 = R2;
    u2R2.multiply(u2);
    publicKeyA = u1G;
    publicKeyA.add(u2R1);
    publicKeyA.normalize();
    publicKeyB = u1G;
    publicKeyB.add(u2R2);
    publicKeyB.normalize();
    return true;
}

I notice, that for some nonces recovery is bad, although verification is good. Bad nonces seems to be random, but r parameter for bad recovery is always small: maximum is 285.
modulus_p - order = 65167-64879 = 288. It is error in my recovery procedure or signing should be bad for nonce which generate small r parameter?
It is error in my recovery procedure, or signing should be bad for nonce which generate small $r$ parameter?

The issue happens because the recovery procedure is a simplified version of the standard method, attributed to Daniel R. L. Brown of Certicom.
Problem happens I guess when in signing, r does not match p.x.value; that is when p.x.value lies in $[n,p)$, where $n$ is the Elliptic Curve group order, and $p$ is the field order.
That has probability about $1-n/p$ to occur by chance. With non-toy parameters that's negligible, e.g. $\approx2^{-127.65}$ for sepk256k1.
If that needed to be avoided for small parameters, we could use the full method, or I guess fix the signature to fail (thus be retried with a different nonce) when the problematic condition arises. Just replace r==0 with p.x.value &gt;= CurvePoint16::ORDER (and perhaps move that up one line).