In fact the baud rate can be set to anything. Instead of using fixed constants, a formula should be used instead.
Old code:
// serial_baud
// set the baud rate, taking in to account the current SystemFrequency
void serial_baud(serial_t *obj, int baudrate)
{
if (baudrate<=1200) {
obj->uart->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200;
return;
}
for (int i = 1; i<17; i++) {
if (baudrate<acceptedSpeeds[i][0]) {
obj->uart->BAUDRATE = acceptedSpeeds[i - 1][1];
return;
}
}
obj->uart->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
}
Better code:
// serial_baud
// set the baud rate, taking in to account the current SystemFrequency
void serial_baud(serial_t *obj, int baudrate)
{
// See https://devzone.nordicsemi.com/question/1181/uart-baudrate-register-values/#reply-1194
// The correct value is baudrate * 2^32 / 16e6 = baudrate * 2^22 / 15625,
// but that doesn't fit into 32 bits, and Cortex M0 has no hardware
// divide, so instead I will do this possibly-over-optimised magic instead!
// I have verified that this produces exactly the same values as the header,
// except for 921600 (which is wrong in the header).
uint32_t br = (baudrate << 8) + (baudrate << 4) - (baudrate << 1) - baudrate
- (baudrate >> 1) - (baudrate >> 4) - (baudrate >> 9) - (baudrate >> 14)
- (baudrate >> 16) - (baudrate >> 17) - (baudrate >> 18) - (baudrate >> 19);
// Round it to 20 bits (see link above).
br = (br + 0x800) & 0xFFFFF000;
// Limit it to the valid range.
if (br < 0x1000)
br = 0x1000;
if (br > 0x10000000)
br = 0x10000000;
obj->uart->BAUDRATE = br;
}
If you look in
serial_api.c
you can see that the nRF51822 code only allows a finite set of baud rates:In fact the baud rate can be set to anything. Instead of using fixed constants, a formula should be used instead.
Old code:
Better code:
I'll do a pull request for this.