Переглянути джерело

* Discovery für ADC und DAC implementiert
* Bei fehlender Discovery wird Fehlerflag gesetzt
* Fehlerflag verhindert Ausführung, erlaubt aber noch Auslesen via I2C (Mainloop-condition)
* Bei einem Fehler werden automatisch DAC und PWM resetted (auch nützlich für Übertemperatur-Prüfung)

Heinrich Blatt 8 місяців тому
батько
коміт
cff9c9979e

+ 10 - 53
main_target.c

@@ -11,56 +11,6 @@
 
 volatile bool mcu_CommandPending= false;
 
-/*
-Scans all the addresses of the peripherals:
-*/
-/*void I2C_scanBus(I2C_Regs *i2c) {
-    printf("1");
-    // **Step 1: Reset I2C Controller if Busy**
-    if (DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) {
-        printf("I2C Bus Busy! Resetting I2C Controller...\n");
-        DL_I2C_disableController(i2c);  // Disable I2C
-        delay_cycles(20000);
-        DL_I2C_enableController(i2c);   // Re-enable I2C
-        delay_cycles(20000);
-    }
-    uint32_t i2c_status;
-    // **Step 2: Scan I2C Bus**
-    for (uint8_t addr = 0x08; addr < 0x78; addr++) {  // Valid I2C Address Range
-        printf("Scanning 0x%02X\n", addr);
-        DL_I2C_startControllerTransfer(i2c, addr, DL_I2C_CONTROLLER_DIRECTION_RX, 1);
-        delay_cycles(5000);
-
-        if (addr != 0x60 && addr != 0x68) {
-            continue;
-        }
-
-        i2c_status = DL_I2C_getControllerStatus(i2c);
-        printf("DL_I2C_getControllerStatus(i2c): %d\n", i2c_status);
-        printf("busy?: %d\n", (i2c_status & DL_I2C_CONTROLLER_STATUS_BUSY));
-        printf("error?: %d\n", (i2c_status & DL_I2C_CONTROLLER_STATUS_ERROR));
-        printf("addr_ack?: %d\n", (i2c_status & DL_I2C_CONTROLLER_STATUS_ADDR_ACK));
-        printf("data_ack?: %d\n", (i2c_status & DL_I2C_CONTROLLER_STATUS_DATA_ACK));
-        printf("arb_lost?: %d\n", (i2c_status & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST));
-        printf("idle?: %d\n", (i2c_status & DL_I2C_CONTROLLER_STATUS_IDLE));
-        printf("busy_bus?: %d\n", (i2c_status & DL_I2C_CONTROLLER_STATUS_BUSY_BUS));
-        
-        if (!(DL_I2C_getControllerStatus(i2c) & DL_I2C_CONTROLLER_STATUS_ERROR)) {
-            printf("Device found at: 0x%02X\n", addr);
-            DL_I2C_disableController(i2c);
-            DL_I2C_enableController(i2c);
-        }else {
-            // Clear the error by resetting the I2C controller
-            printf("Device not found...\n");
-            DL_I2C_disableController(i2c);
-            DL_I2C_enableController(i2c);
-        }
-    }
-
-    //printf("I2C Scan Complete!\n");
-}
-*/
-
 void I2C_controller_INST_IRQHandler(void) {
   // printf("I2C Interrupt Triggered to ADC!\n");
   switch (DL_I2C_getPendingInterrupt(I2C_controller_INST)) { 
@@ -155,7 +105,6 @@ int main(void)
 {   
     SYSCFG_DL_init();
     battery_slotmgr.init();
-    //I2C_scanBus(I2C_controller_INST);
     NVIC_EnableIRQ(I2C_controller_INST_INT_IRQN);
     NVIC_EnableIRQ(I2C_target_INST_INT_IRQN);
     
@@ -172,8 +121,16 @@ int main(void)
             // step 1: update the voltage readings
             battery_slotmgr.read_state(slot);
 
-            // step 2: control loop to adjust the dac / adc values
-            battery_slotmgr.adjust_current(slot);
+            // step 2: control loop to adjust the dac / adc values,
+            // but only if no error happens
+            // (0x80 is the error flag of the state)
+            if (*battery_slots[i].state & 0x80 == 0) {
+                battery_slotmgr.adjust_current(slot);
+            } else {
+                battery_slotmgr.disable(slot);
+            }
+
+            
         }
         
         delay_cycles(DELAY_CYCLE);

+ 35 - 4
src/battery_data/battery.c

@@ -3,6 +3,10 @@
 #include "ti_msp_dl_config.h"
 #include "src/peripherals/dac/dac.h"
 #include "src/peripherals/adc/adc.h"
+#include "src/peripherals/i2c_controller_interface.h"
+// we need the itnerface for the ADC_TARGET_BASE_ADDRESS constant
+// refactor this somewhen to a general constants file
+#include "src/adc/adc_interface.h"
 
 // Permissible charge temperature for LiIon battery is 0.0 degree Celsius to 45.0 degree Celsius
 // Correct temp_threshold yet to be analyzed
@@ -19,10 +23,19 @@ static void set_pwm(uint8_t slot, uint16_t value) {
     battery_slots[slot].pwm_value = value;
     DL_TimerG_setCaptureCompareValue(battery_slots[0].timer, value, DL_TIMER_CC_0_INDEX);
 }
+static void batteryslots_disable(uint8_t slot) {
+    if (battery_slots[slot].dac_value != 0) {
+        set_dac(slot, 0);
+    }
+    if (battery_slots[slot].pwm_value != 0) {
+        set_pwm(slot, 0);
+    }
+}
 
 /*Initialize battery array and default parameters*/
 static void batteryslots_init() {
 
+    // initialize data structures
     battery_slots[0].timer = PWM_0_INST;
 
     for(uint8_t i=0; i< NUM_SLOTS; i++){
@@ -38,9 +51,27 @@ static void batteryslots_init() {
         battery_slots[i].measurement.temperature = 0;
         battery_slots[i].set_current = 0;
 
-        set_dac(i, 0);
         set_pwm(i, 0);
     }
+
+    if (!i2c_discover(DAC_TARGET_ADDRESS)) {
+        // there is only 1 DAC for all 4 slots
+        for(uint8_t i=0; i< NUM_SLOTS; i++) {
+            *battery_slots[i].state = SLOT_ERR_NO_DAC;
+        }
+        // Error state - no I2C on bus - we cannot continue.
+        return
+    }
+
+    for(uint8_t i=0; i< NUM_SLOTS; i++){
+
+        set_dac(i, 0);
+
+        if (!i2c_discover(ADC_TARGET_BASE_ADDRESS+i)) {
+            // this automatically translates to the other addresses
+            *battery_slots[i].state = SLOT_ERR_NO_ADC1+i;
+        }
+    }
 }
 static void batteryslots_read_state(uint8_t slot) {
     /*
@@ -130,14 +161,14 @@ static void batteryslots_adjust_current(uint8_t slot) {
         }
     } else {
         // we have 0 -> stop charging and discharging
-        set_dac(slot, 0);
-        set_pwm(slot, 0);
+        batteryslots_disable(slot);
     }
 }
 
 BatterySlotManager battery_slotmgr = {
     .init = batteryslots_init,
     .read_state = batteryslots_read_state,
-    .adjust_current = batteryslots_adjust_current
+    .adjust_current = batteryslots_adjust_current,
+    .disable = batteryslots_disable
 };
 

+ 9 - 5
src/battery_data/battery.h

@@ -28,7 +28,7 @@ typedef enum{
     SLOT_STATE_HOV= 0x02,
 
     SLOT_WARN_OVERTEMPERATURE = 0x03,
-    SLOT_ERR_OVERTEMPERATURE= 0x04,
+    SLOT_ERR_OVERTEMPERATURE= (0x04 | 0x80), // first bit indicates complete error
 
     // Control error states
     SLOT_WARN_LOWER_DAC_NOT_POSSIBLE=0x10,
@@ -38,10 +38,13 @@ typedef enum{
     SLOT_WARN_HIGHER_PWM_NOT_POSSIBLE=0x14,
 
     // I2C Slave Error states
-    SLOT_ERR_NO_ADC = 0x20,
-    SLOT_ERR_NO_DAC = 0x21,
-    SLOT_ERR_CONFIGBYTE = 0x22,
-    SLOT_ERR_DAC_WRITE_FAILED=0x23,
+    SLOT_ERR_NO_DAC =  (0x20 | 0x80),
+    SLOT_ERR_NO_ADC1 = (0x21 | 0x80),
+    SLOT_ERR_NO_ADC2 = (0x22 | 0x80),
+    SLOT_ERR_NO_ADC3 = (0x23 | 0x80),
+    SLOT_ERR_NO_ADC4 = (0x24 | 0x80),
+    SLOT_ERR_CONFIGBYTE = (0x25 | 0x80),
+    SLOT_ERR_DAC_WRITE_FAILED= (0x26 | 0x80)
 } SlotState;
 
 typedef struct{
@@ -68,6 +71,7 @@ typedef struct {
     void (*init)();
     void (*read_state)(uint8_t slot_id);
     void (*adjust_current)(uint8_t slot_id);
+    void (*disable)(uint8_t slot_id);
 } BatterySlotManager;
 
 extern BatterySlotManager battery_slotmgr;

+ 2 - 0
src/interfaces/i2c_controller_interface.h

@@ -46,6 +46,8 @@ typedef struct {
 } I2CTxPackage;
 extern I2CTxPackage controllerTxPackage;
 
+bool i2c_discover(uint8_t i2c_addr);
+
 /*
 * Since C does not allows to add functions in typedef struct, however a function pointer can be included in Structure in C. This interface provides a standard features of i2c_hal
 */

+ 19 - 7
src/interfaces/i2c_hal.c

@@ -8,13 +8,6 @@
 #include "ti_msp_dl_config.h"
 #include <stdio.h>
 
-volatile bool gRxComplete;
-volatile bool gTxComplete;
-uint8_t gTxPacket[I2C_TX_MAX_PACKET_SIZE];
-uint8_t gRxPacket[I2C_RX_MAX_PACKET_SIZE];
-uint8_t gTxADClen, gTxADCcount;
-uint8_t gRxADClen, gRxADCcount;
-
 /*
 static function is for implementing Data Hiding, access to the static function
 is restricted to the file where they are declared const keyword for
@@ -99,6 +92,25 @@ static bool msp_i2c_read(uint8_t const TARGET_ADDRESS) {
   return true;
 }
 
+/**
+ * this function discovers on the i2c bus the devices from the address
+ * to ensure all relevant bus participants are present
+ */
+ bool i2c_discover(uint8_t i2c_addr) {
+  if (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) {
+      DL_I2C_disableController(I2C_controller_INST);  // Disable I2C
+      DL_I2C_enableController(I2C_controller_INST);   // Re-enable I2C
+  }
+  printf("Scanning 0x%02X\n", i2c_addr);
+  DL_I2C_startControllerTransfer(I2C_controller_INST, i2c_addr, DL_I2C_CONTROLLER_DIRECTION_RX, 1);
+  delay_cycles(5000);
+  i2c_status = DL_I2C_getControllerStatus(I2C_controller_INST);
+  bool found = !(DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_ERROR);
+  DL_I2C_disableController(I2C_controller_INST);
+  DL_I2C_enableController(I2C_controller_INST);
+  return found
+}
+
 I2C_Interface i2c_hal = {
     .write = msp_i2c_write,
     .read = msp_i2c_read,