aboutsummaryrefslogtreecommitdiffstats
path: root/testhal/STM32/STM32F3xx/UART/main.c
blob: 1ef5bb6b9610b182a18b61708da3fe06121e84e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "ch.h"
#include "hal.h"

static virtual_timer_t vt1, vt2;

static void restart(void *p) {

  (void)p;

  chSysLockFromISR();
  uartStartSendI(&UARTD1, 14, "Hello World!\r\n");
  chSysUnlockFromISR();
}

static void ledoff(void *p) {

  (void)p;
  palClearPad(GPIOE, GPIOE_LED3_RED);
}

/*
 * This callback is invoked when a transmission buffer has been completely
 * read by the driver.
 */
static void txend1(UARTDriver *uartp) {

  (void)uartp;
  palSetPad(GPIOE, GPIOE_LED3_RED);
}

/*
 * This callback is invoked when a transmission has physically completed.
 */
static void txend2(UARTDriver *uartp) {

  (void)uartp;
  palClearPad(GPIOE, GPIOE_LED3_RED);
  chSysLockFromISR();
  chVTResetI(&vt1);
  chVTSetI(&vt1, MS2ST(5000), restart, NULL);
  chSysUnlockFromISR();
}

/*
 * This callback is invoked on a receive error, the errors mask is passed
 * as parameter.
 */
static void rxerr(UARTDriver *uartp, uartflags_t e) {

  (void)uartp;
  (void)e;
}

/*
 * This callback is invoked when a character is received but the application
 * was not ready to receive it, the character is passed as parameter.
 */
static void rxchar(UARTDriver *uartp, uint16_t c) {

  (void)uartp;
  (void)c;
  /* Flashing the LED each time a character is received.*/
  palSetPad(GPIOE, GPIOE_LED3_RED);
  chSysLockFromISR();
  chVTResetI(&vt2);
  chVTSetI(&vt2, MS2ST(200), ledoff, NULL);
  chSysUnlockFromISR();
}

/*
 * This callback is invoked when a receive buffer has been completely written.
 */
static void rxend(UARTDriver *uartp) {

  (void)uartp;
}

/*
 * This callback is invoked when configured timeout reached.
 */
static void rxtimeout(UARTDriver *uartp) {

  (void)uartp;
}

/*
 * UART driver configuration structure.
 */
static UARTConfig uart_cfg_1 = {
  txend1,
  txend2,
  rxend,
  rxchar,
  rxerr,
  rxtimeout,
  0,
  38400,
  0,
  USART_CR2_LINEN,
  0
};

/*
 * Application entry point.
 */
int main(void) {

  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Activates the serial driver 1, PA9 and PA10 are routed to USART1.
   */
  uartStart(&UARTD1, &uart_cfg_1);
  palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7));       /* USART1 TX.       */
  palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7));      /* USART1 RX.       */

  /*
   * Starts the transmission, it will be handled entirely in background.
   */
  uartStartSend(&UARTD1, 13, "Starting...\r\n");

  /*
   * Normal main() thread activity, in this demo it does nothing.
   */
  while (true) {
    chThdSleepMilliseconds(500);
  }
}
ss="p">); while (canp->state == CAN_STARTING) osalThreadSleepS(1); if (canp->state == CAN_STOP) { canp->config = config; can_lld_start(canp); canp->state = CAN_READY; } osalSysUnlock(); } /** * @brief Deactivates the CAN peripheral. * * @param[in] canp pointer to the @p CANDriver object * * @api */ void canStop(CANDriver *canp) { osalDbgCheck(canp != NULL); osalSysLock(); osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), "invalid state"); can_lld_stop(canp); canp->state = CAN_STOP; osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET); osalThreadDequeueAllI(&canp->txqueue, MSG_RESET); osalOsRescheduleS(); osalSysUnlock(); } /** * @brief Can frame transmission. * @details The specified frame is queued for transmission, if the hardware * queue is full then the invoking thread is queued. * @note Trying to transmit while in sleep mode simply enqueues the thread. * * @param[in] canp pointer to the @p CANDriver object * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @param[in] ctfp pointer to the CAN frame to be transmitted * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_IMMEDIATE immediate timeout. * - @a TIME_INFINITE no timeout. * . * @return The operation result. * @retval MSG_OK the frame has been queued for transmission. * @retval MSG_TIMEOUT The operation has timed out. * @retval MSG_RESET The driver has been stopped while waiting. * * @api */ msg_t canTransmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp, systime_t timeout) { osalDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= CAN_TX_MAILBOXES)); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { msg_t msg = osalThreadEnqueueTimeoutS(&canp->txqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; } } can_lld_transmit(canp, mailbox, ctfp); osalSysUnlock(); return MSG_OK; } /** * @brief Can frame receive. * @details The function waits until a frame is received. * @note Trying to receive while in sleep mode simply enqueues the thread. * * @param[in] canp pointer to the @p CANDriver object * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @param[out] crfp pointer to the buffer where the CAN frame is copied * @param[in] timeout the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_IMMEDIATE immediate timeout (useful in an * event driven scenario where a thread never blocks * for I/O). * - @a TIME_INFINITE no timeout. * . * @return The operation result. * @retval MSG_OK a frame has been received and placed in the buffer. * @retval MSG_TIMEOUT The operation has timed out. * @retval MSG_RESET The driver has been stopped while waiting. * * @api */ msg_t canReceive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp, systime_t timeout) { osalDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox < CAN_RX_MAILBOXES)); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { msg_t msg = osalThreadEnqueueTimeoutS(&canp->rxqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; } } can_lld_receive(canp, mailbox, crfp); osalSysUnlock(); return MSG_OK; } #if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) /** * @brief Enters the sleep mode. * @details This function puts the CAN driver in sleep mode and broadcasts * the @p sleep_event event source. * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported * by the low level driver. * * @param[in] canp pointer to the @p CANDriver object * * @api */ void canSleep(CANDriver *canp) { osalDbgCheck(canp != NULL); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); if (canp->state == CAN_READY) { can_lld_sleep(canp); canp->state = CAN_SLEEP; osalEventBroadcastFlagsI(&canp->sleep_event, 0); osalOsRescheduleS(); } osalSysUnlock(); } /** * @brief Enforces leaving the sleep mode. * @note The sleep mode is supposed to be usually exited automatically by * an hardware event. * * @param[in] canp pointer to the @p CANDriver object */ void canWakeup(CANDriver *canp) { osalDbgCheck(canp != NULL); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); if (canp->state == CAN_SLEEP) { can_lld_wakeup(canp); canp->state = CAN_READY; osalEventBroadcastFlagsI(&canp->wakeup_event, 0); osalOsRescheduleS(); } osalSysUnlock(); } #endif /* CAN_USE_SLEEP_MODE */ #endif /* HAL_USE_CAN */ /** @} */