free-pdk / easy-pdk-programmer-software

Easy PDK programmer for PADAUK microcontroller
https://free-pdk.github.io/
GNU General Public License v3.0
113 stars 38 forks source link

baud rate for serial monitor #13

Closed cpldcpu closed 5 years ago

cpldcpu commented 5 years ago

The serial UART monitor supposedly uses autobaud. For some reason I can only get it to work with 2400 or 1200 baud. Any higher rate fails. For example 38400, even though it perfectly works with serial to USB adapters.

freepdk commented 5 years ago

Auto baud works fine for me. I tested it with 115200 Baud and higher. It requires to send a special char at the beginning to work: 0x55 should be the first byte to send.

Also, please make sure you do CALIBRATION on target MCU. Otherwise baud rate is any value but not what you expect.

I will provide a small demo "Hello World" program which shows how to implement UART.

freepdk commented 5 years ago

Not cleaned up with new header right now, but you should get the idea from it:


#include <stdbool.h>
#include <stdio.h>

#include "easypdk/pdk14.h"

volatile unsigned int senddata;

void send_bit(void) __interrupt(0)
{
    if( _intrq & 0x40 )
    {
        _intrq &= ~0x40;
        if(senddata)
        {
            _pa = (senddata & 1)?0x80:0;
            senddata >>= 1;
        }
    }
}

int putchar(int c)
{
    while(senddata);
    _inten &= ~0x40;
    senddata = (c << 1) | 0x200;
    _inten |= 0x40;
    return (c);
}

unsigned char _sdcc_external_startup(void)
{
    _clkmd = 0x34; // Use IHRC / 2 = 8 Mhz for system clock, disable watchdog.
    EASY_PDK_CALIBRATE_IHRC(8000000,4000); //TUNE SYSCLK = 8MHz @ 4.000V
    return 0; // perform normal initialization
}

void main(void)
{
    // Set timer 2 for interrupt for 115200 baud.
    _tm2c = 0x20;       // Use IHRC -> 16 Mhz
    _tm2s = 0x01;       // Prescale 1, Scaler 2 ~> 8MHz
    _tm2b = 68;         // Divide by 68 + 1 ~> 115942 Hz (∞115200)
    _pac = 0x80;        // Enable PA.7 as output
    senddata = 0xD55F;  // Setup 2 stop bits, 0x55 char for autobaud, 1 start bit, 5 stop bits (shifted out right)
    _inten = 0x40;      // Enable TM2 interrupt, Send out initial stop bits and autobaud char
    __engint();
    for(;;)
    {
        printf("Hello World!\n");
        for(unsigned long int i=1500000; i>0; i--); // Wait approx. 3s
    }
}
cpldcpu commented 5 years ago

Thanks a lot for your detailed reply!

Sending 0x55 and introducing a little delay after this did the trick. I think you do the same with the 5 stop bits. Looks like I was sending out data too fast. Now it works very stable up to ~1Mbaud, even when the clock is not calibrated. Seems that the STM32 can accomodate for quite some variation in baudrate.

Using printf in SDCC is quite a trap now, btw. When you only send a string terminated with \n it will use "puts" and everything is fine. If you remove the \n it will revert to the full printf implementation which does not fit into PFS154. Quite some erratic behavior that took a while to understand.