usart.c 7.27 KB
Newer Older
mux's avatar
mux committed
1
#include <stdio.h>
2
3
4
5
6
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_usart.h>

#include "misc.h"
mux's avatar
mux committed
7
8
#include "mpconfig.h"
#include "obj.h"
9
10
11
12
#include "usart.h"

static bool is_enabled;

mux's avatar
mux committed
13
14
15
16
17
18
19
typedef enum {
    PYB_USART_1 = 1,
    PYB_USART_2 = 2,
    PYB_USART_3 = 3,
    PYB_USART_6 = 4,
    PYB_USART_MAX = 4,
} pyb_usart_t;
20

mux's avatar
mux committed
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
static USART_TypeDef *usart_get_base(pyb_usart_t usart_id) {
    USART_TypeDef *USARTx=NULL;

    switch (usart_id) {
        case PYB_USART_1:
            USARTx = USART1;
            break;
        case PYB_USART_2:
            USARTx = USART2;
            break;
        case PYB_USART_3:
            USARTx = USART3;
            break;
        case PYB_USART_6:
            USARTx = USART6;
            break;
    }

    return USARTx;
}

void usart_init(pyb_usart_t usart_id, uint32_t baudrate) {
    USART_TypeDef *USARTx=NULL;

    uint32_t GPIO_Pin=0;
    uint8_t  GPIO_AF_USARTx=0;
    GPIO_TypeDef* GPIO_Port=NULL;
    uint16_t GPIO_PinSource_TX=0;
    uint16_t GPIO_PinSource_RX=0;

    uint32_t RCC_APBxPeriph=0;
    void (*RCC_APBxPeriphClockCmd)(uint32_t, FunctionalState)=NULL;

    switch (usart_id) {
        case PYB_USART_1:
            USARTx = USART1;

            GPIO_Port = GPIOA;
            GPIO_AF_USARTx = GPIO_AF_USART1;
            GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
            GPIO_PinSource_TX = GPIO_PinSource9;
            GPIO_PinSource_RX = GPIO_PinSource10;

            RCC_APBxPeriph = RCC_APB2Periph_USART1;
            RCC_APBxPeriphClockCmd =RCC_APB2PeriphClockCmd;
            break;
        case PYB_USART_2:
            USARTx = USART2;

            GPIO_Port = GPIOD;
            GPIO_AF_USARTx = GPIO_AF_USART2;
            GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
            GPIO_PinSource_TX = GPIO_PinSource5;
            GPIO_PinSource_RX = GPIO_PinSource6;

            RCC_APBxPeriph = RCC_APB1Periph_USART2;
            RCC_APBxPeriphClockCmd =RCC_APB1PeriphClockCmd;
            break;
        case PYB_USART_3:
            USARTx = USART3;

            GPIO_Port = GPIOD;
            GPIO_AF_USARTx = GPIO_AF_USART3;
            GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
            GPIO_PinSource_TX = GPIO_PinSource8;
            GPIO_PinSource_RX = GPIO_PinSource9;

            RCC_APBxPeriph = RCC_APB1Periph_USART3;
            RCC_APBxPeriphClockCmd =RCC_APB1PeriphClockCmd;
            break;
        case PYB_USART_6:
            USARTx = USART6;

            GPIO_Port = GPIOC;
            GPIO_AF_USARTx = GPIO_AF_USART6;
            GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
            GPIO_PinSource_TX = GPIO_PinSource6;
            GPIO_PinSource_RX = GPIO_PinSource7;

            RCC_APBxPeriph = RCC_APB2Periph_USART6;
            RCC_APBxPeriphClockCmd =RCC_APB2PeriphClockCmd;
            break;
    }

    /* Initialize USARTx */
    RCC_APBxPeriphClockCmd(RCC_APBxPeriph, ENABLE);

    GPIO_PinAFConfig(GPIO_Port, GPIO_PinSource_TX, GPIO_AF_USARTx);
    GPIO_PinAFConfig(GPIO_Port, GPIO_PinSource_RX, GPIO_AF_USARTx);
110
111

    GPIO_InitTypeDef GPIO_InitStructure;
mux's avatar
mux committed
112
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin;
113
114
115
116
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
mux's avatar
mux committed
117
    GPIO_Init(GPIO_Port, &GPIO_InitStructure);
118
119

    USART_InitTypeDef USART_InitStructure;
mux's avatar
mux committed
120
    USART_InitStructure.USART_BaudRate = baudrate;
121
122
123
124
125
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
mux's avatar
mux committed
126
    USART_Init(USARTx, &USART_InitStructure);
127

mux's avatar
mux committed
128
    USART_Cmd(USARTx, ENABLE);
129
130
131
132
133
134
135
136
137
138
}

bool usart_is_enabled(void) {
    return is_enabled;
}

bool usart_rx_any(void) {
    return USART_GetFlagStatus(USART6, USART_FLAG_RXNE) == SET;
}

mux's avatar
mux committed
139
140
141
int usart_rx_char(pyb_usart_t usart_id) {
    USART_TypeDef *USARTx= usart_get_base(usart_id);
    return USART_ReceiveData(USARTx);
142
143
}

mux's avatar
mux committed
144
145
146
147
148
void usart_tx_char(pyb_usart_t usart_id, int c) {
    USART_TypeDef *USARTx = usart_get_base(usart_id);
    // wait until the end of any previous transmission
    uint32_t timeout = 100000;
    while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET && --timeout > 0) {
149
    }
mux's avatar
mux committed
150
    USART_SendData(USARTx, c);
151
152
}

mux's avatar
mux committed
153
void usart_tx_str(pyb_usart_t usart_id, const char *str) {
154
    for (; *str; str++) {
mux's avatar
mux committed
155
        usart_tx_char(usart_id, *str);
156
157
158
    }
}

mux's avatar
mux committed
159
void usart_tx_strn_cooked(pyb_usart_t usart_id, const char *str, int len) {
160
161
    for (const char *top = str + len; str < top; str++) {
        if (*str == '\n') {
mux's avatar
mux committed
162
            usart_tx_char(usart_id, '\r');
163
        }
mux's avatar
mux committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
        usart_tx_char(usart_id, *str);
    }
}


/******************************************************************************/
/* Micro Python bindings                                                      */

typedef struct _pyb_usart_obj_t {
    mp_obj_base_t base;
    pyb_usart_t usart_id;
    bool is_enabled;
} pyb_usart_obj_t;

178
179
180
181
182
183
184
185
186
static mp_obj_t usart_obj_status(mp_obj_t self_in) {
    // TODO make it check the correct USART port!
    if (usart_rx_any()) {
        return mp_const_true;
    } else {
        return mp_const_false;
    }
}

mux's avatar
mux committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
static mp_obj_t usart_obj_rx_char(mp_obj_t self_in) {
    mp_obj_t ret = mp_const_none;
    pyb_usart_obj_t *self = self_in;

    if (self->is_enabled) {
        ret =  mp_obj_new_int(usart_rx_char(self->usart_id));
    }
    return ret;
}

static mp_obj_t usart_obj_tx_char(mp_obj_t self_in, mp_obj_t c) {
    pyb_usart_obj_t *self = self_in;
    if (self->is_enabled) {
        usart_tx_char(self->usart_id, mp_obj_get_int(c));
    }
    return mp_const_none;
}

static mp_obj_t usart_obj_tx_str(mp_obj_t self_in, mp_obj_t s) {
    pyb_usart_obj_t *self = self_in;
    if (self->is_enabled) {
mux's avatar
mux committed
208
209
210
211
        if (MP_OBJ_IS_TYPE(s, &str_type)) {
            const char *str = qstr_str(mp_obj_get_qstr(s));
            usart_tx_str(self->usart_id, str);
        }
212
    }
mux's avatar
mux committed
213
214
215
216
217
218
219
220
    return mp_const_none;
}

static void usart_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
    pyb_usart_obj_t *self = self_in;
    print(env, "<Usart %lu>", self->usart_id);
}

221
static MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_status_obj, usart_obj_status);
mux's avatar
mux committed
222
223
224
225
226
static MP_DEFINE_CONST_FUN_OBJ_1(usart_obj_rx_char_obj, usart_obj_rx_char);
static MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_char_obj, usart_obj_tx_char);
static MP_DEFINE_CONST_FUN_OBJ_2(usart_obj_tx_str_obj, usart_obj_tx_str);

static const mp_method_t usart_methods[] = {
227
    { "status", &usart_obj_status_obj },
mux's avatar
mux committed
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    { "recv_chr", &usart_obj_rx_char_obj },
    { "send_chr", &usart_obj_tx_char_obj },
    { "send", &usart_obj_tx_str_obj },
    { NULL, NULL },
};

static const mp_obj_type_t usart_obj_type = {
    { &mp_const_type },
    "Usart",
    .print = usart_obj_print,
    .methods = usart_methods,
};

mp_obj_t pyb_Usart(mp_obj_t usart_id, mp_obj_t baudrate) {
    if (mp_obj_get_int(usart_id)>PYB_USART_MAX) {
        return mp_const_none;
    }

    /* init USART */
    usart_init(mp_obj_get_int(usart_id), mp_obj_get_int(baudrate));

    pyb_usart_obj_t *o = m_new_obj(pyb_usart_obj_t);
    o->base.type = &usart_obj_type;
    o->usart_id = mp_obj_get_int(usart_id);
    o->is_enabled = true;
    return o;
254
}