]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/commitdiff
Added watchdog stop feature and refactored a bit the H-Bridge driver. Untested, might...
authorCarlos Miguel Jenkins Pérez <carlos@jenkins.co.cr>
Sun, 9 Jun 2013 13:03:49 +0000 (15:03 +0200)
committerCarlos Miguel Jenkins Pérez <carlos@jenkins.co.cr>
Sun, 9 Jun 2013 13:03:49 +0000 (15:03 +0200)
rpp/include/drv/hbridge.h
rpp/include/rpp/can.h
rpp/include/rpp/hbr.h
rpp/src/drv/hbridge.c
rpp/src/rpp/aout.c
rpp/src/rpp/hbr.c

index 9b5076c54f9c25ec5c0b5f9d50bab82e89999574..89ce15c8085b169c7560ce3251840e81be0af2f1 100644 (file)
@@ -1,34 +1,37 @@
-/*
- * hbridge.h
+/**
+ * RPP driver implementation for H-Bridge header file.
  *
- *  Created on: 9.11.2012
- *      Author: Michal Horn
+ * @file hbridge.h
+ *
+ * @copyright Copyright (C) 2012-2013 Czech Technical University in Prague
+ *
+ * @author Michal Horn
+ * @author Carlos Jenkins <carlos@jenkins.co.cr>
  */
 
-#ifndef HBRIDGE_H_
-#define HBRIDGE_H_
 
-//#include "drv_spi.h"
-//#include "FreeRTOS.h"
-//#include "os_task.h"
-//#include "ti_drv_het.h"
-//#include "hal_gpio_tms570.h"
+#ifndef __DRV_HBR_H
+#define __DRV_HBR_H
+
 #include "drv/drv.h"
 
-/* Called when whole transfer is finished */
-int hbr_spi_wdg_callback(struct spi_drv * ifc, int code, struct spi_msg_head * msg);
-int hbr_spi_wdg_transfer();
+// Watchdog related
+int8_t drv_hbr_wdg_start();
+int8_t drv_hbr_wdg_stop();
+
+// Basic H-Bridge API
+void drv_hbr_set_en(int value);
+void drv_hbr_set_dir(int direction);
+int8_t drv_hbr_pwm_set_signal(double period, uint32_t duty);
+void drv_hbr_pwm_set_duty(uint8_t percent);
+int8_t drv_hbr_pwm_start();
+void drv_hbr_pwm_stop();
 
-void hbr_pwm_set_signal(double period, uint32_t duty);
-int hbr_pwm_start();
-void hbr_pwm_stop();
-void hbr_pwm_set_duty(uint8_t percent);
-uint32_t hbr_pwm_get_duty();
-double hbr_pwm_get_period();
-void hbr_set_dir(int direction);
-int hbr_get_dir();
-void hbr_set_en(int value);
-int hbr_get_en();
+// Extended H-Bridge API
+uint32_t drv_hbr_pwm_get_duty();
+double drv_hbr_pwm_get_period();
+int drv_hbr_get_dir();
+int drv_hbr_get_en();
 
 
-#endif /* HBRIDGE_H_ */
+#endif /* __DRV_HBR_H */
index caec828437651234ac613507f5bb9692b35632ed..c57f5febcd2783dd21a8362c748f4090f9d9a421 100644 (file)
@@ -18,7 +18,7 @@
  * Call this method before using this module.
  *
  * @return SUCCESS if initialization successful.\n
- *          FAILURE if module already initialized.
+ *         FAILURE if module already initialized.
  */
 int8_t rpp_can_init();
 
index 5fc5411fa01fcb4ce2f21ad4c4fb1fa1a8465bb6..09abf7c6507204217b8db44adadcd53ddd59bd5c 100644 (file)
@@ -18,7 +18,7 @@
  * Call this method before using this module.
  *
  * @return SUCCESS if initialization successful.\n
- *          FAILURE if module already initialized.
+ *         FAILURE if module already initialized.
  */
 int8_t rpp_hbr_init();
 
@@ -36,7 +36,8 @@ int8_t rpp_hbr_init();
  *                      ~18kHz (18181.818181818 Hz to be precise) is used.
  *
  * @return SUCCESS if successful.\n
- *          FAILURE if H-Bridge was already enabled.
+ *         FAILURE if H-Bridge was already enabled or watchdog task could not
+ *                 be created.
  *
  * @note Period considerations from Software perspective (hardware verification
  * required):
@@ -93,7 +94,7 @@ int8_t rpp_hbr_control(double cmd);
  * controlled again until another call to rpp_hbr_enable() is made.
  *
  * @return SUCCESS if successful.\n
- *          FAILURE if H-Bridge was disabled already.
+ *         FAILURE if H-Bridge was disabled already.
  */
 int8_t rpp_hbr_disable();
 
index 343d7a0cf9aa4affd2c8cfa4b9a5415f4d90b108..0f673877b191e2df7b60b11a2bda38e7fbc7573a 100644 (file)
-/*
- * hbridge.c
+/* Copyright (C) 2013 Czech Technical University in Prague
  *
- *  Created on: 9.11.2012
- *      Author: Michal Horn
+ * Authors:
+ *     - Michal Horn
+ *     - Carlos Jenkins <carlos@jenkins.co.cr>
  *
- *  This file contains functions to control H-bridge.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
- *  Periodical hbr watchdog reset command sending once it is sent manualy.
- *  PWM for HBR control
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * File : ain.c
+ * Abstract:
+ *     RPP driver implementation for HBR.
+ *
+ * References:
+ *     hbridge.h
  */
 
-//TODO: HBR_DIR and HBR_EN toggling
+// This file contains functions to control H-bridge.
+// A keep-alive watchdog is implemented.
+// PWM is available for HBR control.
+
 
-//#include "drv_hbridge.h"
 #include "drv/drv.h"
 
-/** Flag variable if watchdog command has been sent one before **/
-static char hbr_spi_initialized;
-/** Prepared command to be send on SPI, default value is watchdog reset command **/
+//Flag variable if pwm was initialized and is ready to start.
+static boolean_t pwm_initialized = FALSE;
+
+
+/// Watchdog Task --------------------------------------------------------------
+
+// Prepared command to be send on SPI.
+// Default value is watchdog reset command.
 uint16_t hbr_spi_wdg_tx = 0x03DB;
-/** Response from SPI **/
-uint16_t hbr_spi_wdg_rx = 0;
-/** Shadow variable of command being send on SPI, default value is watchdog reset command **/
+
+// Shadow variable of hbr_spi_wdg_tx
 uint16_t hbr_spi_wdg_tx_shd = 0x03DB;
-/** Response from SPI **/
+
+// Response from SPI.
+uint16_t hbr_spi_wdg_rx = 0;
+
+// Shadow variable of hbr_spi_wdg_shd
 uint16_t hbr_spi_wdg_rx_shd = 0;
-/** Flag variable if pwm was initialized and is ready to start **/
-uint8_t hbr_pwm_initialized = 0;
-/** SPI message format definition for watchdog reset command **/
+
+/**
+ * @brief   SPI callback function
+ *
+ * This function is called each time SPI transfer finishes.
+ * Gets response and prepare command for next sending.
+ * Copy response from shadow variable,
+ * Copy prepared command to shadow variable
+ *
+ * @param[in]   ifc     Pointer to SPI driver structure
+ * @param[in]   code    SPI transfer status code
+ * @param[in]   msg     Pointer to message definition structure
+ *
+ * @return  always zero
+ */
+int drv_hbr_spi_wdg_callback(struct spi_drv* ifc, int code,
+                         struct spi_msg_head* msg)
+{
+    if (code == SPI_MSG_FINISHED) {
+        hbr_spi_wdg_rx = hbr_spi_wdg_rx_shd;
+        hbr_spi_wdg_tx_shd = hbr_spi_wdg_tx;
+    }
+    return 0;
+}
+
+
+// SPI message format definition for watchdog reset command
 spi_msg_head_t hbr_spi_wdg = {
         .flags = 0,
         .addr = 0,
         .rq_len = 2,
         .tx_buf = (uint8_t*) &hbr_spi_wdg_tx_shd,
         .rx_buf = (uint8_t*) &hbr_spi_wdg_rx_shd,
-        .callback = hbr_spi_wdg_callback,
+        .callback = drv_hbr_spi_wdg_callback,
         .private = 1
 };
 
 /**
- * @brief   Watchdog reset task function
+ * Watchdog FreeRTOS Task function.
  *
  * Select appropriate spi address
  * Initialize task timer
- * Send watchdog reset command each 10ms
+ * Send watchdog keep-alive command each 10ms.
  *
- * @param[in]   pvParameters    Pointer to parameter, not used
+ * @param[in]   p    Pointer to parameter, unused.
  */
-void hbr_wdg_task(void *pvParameters) {
-    spi_drv_t *ifc;
+void drv_hbr_wdg_task(void *p)
+{
+    spi_drv_t* ifc;
     ifc = spi_find_drv(NULL, 4);
-    if (ifc == NULL)
-        return;
+
+    if(ifc == NULL) {
+        vTaskSuspend(NULL);
+    }
 
     portTickType xLastWakeTime;
     xLastWakeTime = xTaskGetTickCount();
-    for( ;; ) {
+    while(TRUE) {
         spi_msg_rq_ins(ifc, &hbr_spi_wdg);
-        vTaskDelayUntil( &xLastWakeTime, ( 10 / portTICK_RATE_MS ) );
+        vTaskDelayUntil(&xLastWakeTime, (10 / portTICK_RATE_MS));
     }
 }
 
+
+/// Watchdog API ---------------------------------------------------------------
+static boolen_t wdg_running = FALSE;
+static xTaskHandle wdg_handle = NULL;
+
 /**
- * @brief   SPI callback function
- *
- * This function is called each time SPI transfer finishes.
- * Gets response and prepare command for next sending.
- * Copy response from shadow variable,
- * Copy prepared command to shadow variable
+ * Start the watchdog task to send keep-alive commands periodically to H-Bridge.
  *
- * @param[in]   ifc     Pointer to SPI driver structure
- * @param[in]   code    SPI transfer status code
- * @param[in]   msg     Pointer to message definition structure
- *
- * @return  always zero
+ * @return SUCCESS if watchdog could be started.\n
+ *         FAILURE if H-Bridge not setup (call hbr_set_signal() first), the
+ *                 watchdog is running already or the task could not be created.
  */
-int hbr_spi_wdg_callback(struct spi_drv * ifc, int code, struct spi_msg_head * msg) {
-    if (code == SPI_MSG_FINISHED) {
-        hbr_spi_wdg_rx = hbr_spi_wdg_rx_shd;
-        hbr_spi_wdg_tx_shd = hbr_spi_wdg_tx;
+int8_t drv_hbr_wdg_start()
+{
+    if(!pwm_initialized) {
+        return FAILURE;
     }
-    return 0;
+
+    if(wdg_running) {
+        return FAILURE;
+    }
+
+    if(xTaskCreate(drv_hbr_wdg_task,
+                   (const signed char *)"hbr_wdg_task",
+                   300, NULL, 1, &wdg_handle) != pdPASS) {
+        return FAILURE;
+    }
+
+    wdg_running = TRUE;
+    return SUCCESS;
 }
 
+
 /**
- * @brief   Start periodically sending watchdog reset commands
- *
- * If watchdog command is going to be send for the first time, create new thread and start sending the command each 10ms
+ * Stop the watchdog task.
  *
- * @return SPI response or -1 when thread creation failed.
+ * @return SUCCESS if watchdog could be stopped.\n
+ *         FAILURE if watchdog wasn't running.
  */
-int hbr_spi_wdg_transfer() {
-    if (!hbr_spi_initialized) {
-        hbr_spi_initialized = 1;
+int8_t drv_hbr_wdg_stop()
+{
+    if(!pwm_initialized) {
+        return FAILURE;
+    }
 
-        if (xTaskCreate(hbr_wdg_task, (const signed char *)"HBR_WDG", 300, NULL, 1, NULL ) != pdPASS) {
-            return -1;
-        }
+    if(!wdg_running) {
+        return FAILURE;
     }
-    return hbr_spi_wdg_rx;
+
+    vTaskDelete(&wdg_handle);
+    wdg_running = FALSE;
+    return SUCCESS;
 }
 
+
+/// H-Bridge API ---------------------------------------------------------------
 /**
  * @brief Set PWM period and duty cycle to HBR_PWM pin
  *
@@ -112,49 +180,53 @@ int hbr_spi_wdg_transfer() {
  * @param[in]   period      Period of PWM in us
  * @param[in]   duty        Width of duty in %
  */
-void hbr_pwm_set_signal(double period, uint32_t duty)
+int8_t drv_hbr_pwm_set_signal(double period, uint32_t duty)
 {
-    // FIXME Should not be returning void, the function can not report if it
-    // was successful.
     hetSIGNAL_t tmp_signal;
 
     if(duty > 100) {
-        return;
+        return FAILURE;
     }
 
     if(period < 1) {
-        return;
+        return FAILURE;
     }
 
     tmp_signal.duty   = duty;
     tmp_signal.period = period;
     pwmSetSignal(hetRAM1, pwm0, tmp_signal);
 
-    hbr_pwm_initialized = TRUE;
+    pwm_initialized = TRUE;
+
+    return SUCCESS;
 }
 
+
 /**
- * @brief Start PWM on HBR_PWM pin
+ * Start PWM on HBR_PWM pin
  *
  * If PWM was set previously by hbr_pwm_set_signal function, this procedure starts it.
  * Otherwise function returns and PWM is not started.
  *
  * @return  0 if success, -1 when PWM was not yes set.
  */
-int hbr_pwm_start() {
-    if (hbr_pwm_initialized) {
+int8_t drv_hbr_pwm_start()
+{
+    if (pwm_initialized) {
+
         pwmStart(hetRAM1, pwm0);
-        return 0;
-    }
-    else {
-        return -1;
+        return SUCCESS;
+
+    } else {
+
+        return FAILURE;
     }
 }
 
 /**
  * @brief Stop PWM on HBR_PWM pin
  */
-void hbr_pwm_stop() {
+void drv_hbr_pwm_stop() {
     pwmStop(hetRAM1, pwm0);
 }
 
@@ -170,7 +242,7 @@ void hbr_pwm_set_duty(uint8_t percent)
  *
  * @return      Duty width of PWM in %
  */
-uint32_t hbr_pwm_get_duty() {
+uint32_t drv_hbr_pwm_get_duty() {
     hetSIGNAL_t tmp_signal;
     tmp_signal = pwmGetSignal(hetRAM1, pwm0);
     return tmp_signal.duty;
@@ -181,7 +253,7 @@ uint32_t hbr_pwm_get_duty() {
  *
  * @return      Period of PWM in us
  */
-double hbr_pwm_get_period() {
+double drv_hbr_pwm_get_period() {
     hetSIGNAL_t tmp_signal;
     tmp_signal = pwmGetSignal(hetRAM1, pwm0);
     return tmp_signal.period;
@@ -193,7 +265,7 @@ double hbr_pwm_get_period() {
  *
  *  @param[in]  direction   If O, set hbr_dir to 0, otherwise to 1
  */
-void hbr_set_dir(int direction) {
+void drv_hbr_set_dir(int direction) {
     hal_gpio_pin_set_value(PIN_DSC_HBRDIR, direction);
 }
 
@@ -202,7 +274,7 @@ void hbr_set_dir(int direction) {
  *
  *  @return return 0 or 1 - the value of hbr_dir
  */
-int hbr_get_dir() {
+int drv_hbr_get_dir() {
     return hal_gpio_pin_get_value(PIN_DSC_HBRDIR);
 }
 
@@ -211,7 +283,7 @@ int hbr_get_dir() {
  *
  *  @param[in]  direction   If O, set hbr_en to 0, otherwise to 1
  */
-void hbr_set_en(int value) {
+void drv_hbr_set_en(int value) {
     hal_gpio_pin_set_value(PIN_DSC_HBREN, value);
 }
 
@@ -220,6 +292,6 @@ void hbr_set_en(int value) {
  *
  *  @return return 0 or 1 - the value of hbr_en
  */
-int hbr_get_en() {
+int drv_hbr_get_en() {
     return hal_gpio_pin_get_value(PIN_DSC_HBREN);
 }
index a20d7b331f99a05d750b9bc977829b7356f5fa44..25792108686ad0cc6e0a4918231b922ed08b658c 100644 (file)
@@ -44,10 +44,11 @@ int8_t rpp_aout_init()
     initialized = TRUE;
 
     // Configure board
-    rpp_aout_setup(1, FALSE);
-    rpp_aout_setup(2, FALSE);
-    rpp_aout_setup(3, FALSE);
-    rpp_aout_setup(4, FALSE);
+    // FIXME find out why board has default output of ~3.8V
+    //rpp_aout_setup(1, FALSE);
+    //rpp_aout_setup(2, FALSE);
+    //rpp_aout_setup(3, FALSE);
+    //rpp_aout_setup(4, FALSE);
 
     return SUCCESS;
 }
index deb8a6a471f9ba8e80f01e4e7993d2908c416a35..c7296a386141d1a3822e5ab18d420ea432f61202 100644 (file)
@@ -51,10 +51,10 @@ int8_t rpp_hbr_init()
 static void rpp_hdr_reset()
 {
     #if rppCONFIG_DRV == 1
-    hbr_set_en(LOW);
-    hbr_pwm_set_duty(0);
-    hbr_pwm_stop();
-    hbr_set_dir(LOW);
+    drv_hbr_set_en(LOW);
+    drv_hbr_pwm_set_duty(0);
+    drv_hbr_pwm_stop();
+    drv_hbr_set_dir(LOW);
     #endif
 }
 
@@ -72,9 +72,13 @@ int8_t rpp_hbr_enable(int32_t period)
     }
 
     #if rppCONFIG_DRV == 1
-    hbr_pwm_set_signal(period, 0);
+    // Configure H-Bridge
+    drv_hbr_pwm_set_signal(period, 0);
     rpp_hdr_reset();
-    // FIXME enable watchdog task
+    // Start watchdog
+    if(drv_hbr_wdg_start() != SUCCESS) {
+        return FAILURE;
+    }
     #endif
 
     enabled = TRUE;
@@ -107,17 +111,17 @@ int8_t rpp_hbr_control(double cmd)
     /// Enabled, configure
     // Set direction
     if(scaled < 0) {
-        hbr_set_dir(LOW);
+        drv_hbr_set_dir(LOW);
     } else {
-        hbr_set_dir(HIGH);
+        drv_hbr_set_dir(HIGH);
     }
 
     // Set PWM duty cycle
-    hbr_pwm_set_duty(abs(scaled));
-    hbr_pwm_start();
+    drv_hbr_pwm_set_duty(abs(scaled));
+    drv_hbr_pwm_start();
 
     // Enable H-Bridge
-    hbr_set_en(HIGH);
+    drv_hbr_set_en(HIGH);
     #endif
 
     return SUCCESS;
@@ -130,6 +134,13 @@ int8_t rpp_hbr_disable()
         return FAILURE;
     }
 
+    #if rppCONFIG_DRV == 1
+    // We ignore is watchdog could not be stopped, because is harmless.
+    // It would be worse if we just could not stop the H-Bridge just because
+    // the watchdog could not be stopped.
+    drv_hbr_wdg_stop();
+    #endif
+
     rpp_hdr_reset();
     enabled = FALSE;