smBus communication testing for fan driver IC in STM32 with C - c

I developed a library for fan IC which use smbus protocol. However ı have some problems and questions.
1 -) what is diff between master and slave for smbus? whether the IC should be slave or master is not specified in the datasheet. Therefore, how can ı decide that stm32 developer board should be slave or master.
2-) unfortunately, ı cannot try my code because fan driver IC ı have not received yet sensor. Do u know any method to test my code. Maybe ardunio library.
3-) to receive data, ı firstly tranmit the register address of data ı want to read. is it correct.
You can find datasheet of IC and code ı wrote below
C file
#include "smbusDriver.h"
#include "stm32f0xx_hal_smbus.h"
#include "stm32f0xx_hal.h"
#include "smbusDriver.h"
resultConditions_t InitializeDriver(SMBUS_HandleTypeDef *hsmbus, uint8_t address, addressValues_t *Daddress){
Daddress->Fields.configurationRegisterAddress = 0x20;
Daddress->Fields.FanStatusRegisterAddress = 0x24;
Daddress->Fields.FanStallRegisterAddress = 0x25;
Daddress->Fields.FanSpinRegisterAddress = 0x26;
Daddress->Fields.DriveFailStatusAddress = 0x27;
Daddress->Fields.FanInterruptEnableRegisterAddress = 0x29;
Daddress->Fields.PwmPolarityRegisterAddress = 0x2A;
Daddress->Fields.PwmOutputTypeRegisterAddress = 0x2B;
Daddress->Fields.PwmFrequency45Address = 0x2C;
Daddress->Fields.PwmFrequency123Address = 0x2D;
Daddress->Fields.PwmDivider1Address = 0x31;
Daddress->Fields.PwmDivider2Address = 0x41;
Daddress->Fields.PwmDivider3Address = 0x51;
Daddress->Fields.PwmDivider4Address = 0x61;
Daddress->Fields.PwmSettingAddress1 = 0x30;
Daddress->Fields.PwmSettingAddress2 = 0x40;
Daddress->Fields.PwmSettingAddress3 = 0x50;
Daddress->Fields.PwmSettingAddress4 = 0x60;
resultConditions_t result = RESULT_OK;
uint8_t buf[2];
configuration_t confDriver;
confDriver.Fields.MASK = 0 ; // Alert pin activated.
confDriver.Fields.DIS_TO = 0; // smBUS enabled. If 1, I2C is compatible
confDriver.Fields.WD_EN = 0; // Watchdog is not enabled
confDriver.Fields.DRECK = 1; // Enabled internal clock
confDriver.Fields.USECK = 0; // Connecting internal oscillator
FanInterruptEnableRegister_t FanIntEn;
FanIntEn.Fields.F1ITEN = 1;
FanIntEn.Fields.F2ITEN = 1;
FanIntEn.Fields.F3ITEN = 1;
FanIntEn.Fields.F4ITEN = 1;
FanIntEn.Fields.F5ITEN = 0;
PwmPolarityRegister_t PwmPolarity;
PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
PwmPolarity.Fields.PLRITY1 = 0; // FF => 255, 00 => 00
PwmOutputTypeRegister_t OutputType;
OutputType.Fields.PMOT1 = 0;
OutputType.Fields.PMOT2 = 0;
OutputType.Fields.PMOT3 = 0;
OutputType.Fields.PMOT4 = 0;
PwmFrequency45_t BaseFrequency_45;
PwmFrequency123_t BaseFrequency_123;
BaseFrequency_45.Fields.PwmFrequency4 = 0; // 26kHz
BaseFrequency_45.Fields.PwmFrequency5 = 0; // 26kHz
BaseFrequency_123.Fields.PwmFrequency1 = 0; // 26kHz
BaseFrequency_123.Fields.PwmFrequency2 = 0; // 26kHz
BaseFrequency_123.Fields.PwmFrequency3 = 0; // 26kHz
PwmDividerRegister_t Divider;
Divider.Fields.pwmDivider_1 = 0x01; // PWM Divider
Divider.Fields.pwmDivider_2 = 0x01; // PWM Divider
Divider.Fields.pwmDivider_3 = 0x01; // PWM Divider
Divider.Fields.pwmDivider_4 = 0x01; // PWM Divider
HAL_SMBUS_Init(hsmbus);
HAL_Delay(10);
uint16_t DeviceAddress = 0x0000;
DeviceAddress = DeviceAddress | address;
result = HAL_SMBUS_IsDeviceReady(hsmbus, DeviceAddress, 5 , 1000);
if (result != RESULT_OK) return result;
HAL_SMBUS_EnableAlert_IT(hsmbus);
if (result != RESULT_OK) return result;
HAL_SMBUS_EnableListen_IT(hsmbus);
if (result != RESULT_OK) return result;
HAL_Delay(20);
buf[0] = Daddress->Fields.configurationRegisterAddress; // The configuration of board is set
buf[1] = confDriver.value;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result != RESULT_OK) return result;
HAL_Delay(20);
buf[0] = Daddress->Fields.FanInterruptEnableRegisterAddress; // If any alert shows up, Fans can interrupt the operation
buf[1] = FanIntEn.value;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmPolarityRegisterAddress; // The high to high, low to low
buf[1] = PwmPolarity.value;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmOutputTypeRegisterAddress; // Pull-push and Open Drain choose
buf[1] = OutputType.value;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmFrequency45Address; // Base Frequency 4-5
buf[1] = BaseFrequency_45.value;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result; // Base Frequency 1-2-3
buf[0] = Daddress->Fields.PwmFrequency123Address;
buf[1] = BaseFrequency_123.value;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmDivider1Address; // Divider of frequency => frequency / divide factor (Duty Cycle is not affected)
buf[1] = Divider.Fields.pwmDivider_1;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmDivider2Address; // Divider of frequency
buf[1] = Divider.Fields.pwmDivider_2;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmDivider3Address; // Divider of frequency
buf[1] = Divider.Fields.pwmDivider_3;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
HAL_Delay(20);
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmDivider4Address; // Divider of frequency
buf[1] = Divider.Fields.pwmDivider_4;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result != RESULT_OK) return result;
return result;
}
resultConditions_t setPwmConfig(uint8_t Pwm, addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
resultConditions_t result = HAL_OK;
PwmSettings_t pwmSet;
uint8_t buf[2];
pwmSet.Fields.pwmSettings1 = Pwm;
pwmSet.Fields.pwmSettings2 = Pwm;
pwmSet.Fields.pwmSettings3 = Pwm;
pwmSet.Fields.pwmSettings4 = Pwm;
uint16_t DeviceAddress = 0x0000;
DeviceAddress = DeviceAddress | address;
buf[0] = Daddress->Fields.PwmSettingAddress1; // Pwm set
buf[1] = pwmSet.Fields.pwmSettings1;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> %100 Duty Cycle /\ 0x00 -> %0 Duty Cycle
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmSettingAddress2; // Pwm set
buf[1] = pwmSet.Fields.pwmSettings2;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> %100 Duty Cycle /\ 0x00 -> %0 Duty Cycle
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmSettingAddress3; // Pwm set
buf[1] = pwmSet.Fields.pwmSettings3;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> %100 Duty Cycle /\ 0x00 -> %0 Duty Cycle
if (result != RESULT_OK) return result;
buf[0] = Daddress->Fields.PwmSettingAddress4; // Pwm set
buf[1] = pwmSet.Fields.pwmSettings4;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus,DeviceAddress << 0,buf,2,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC); // => 0xHH -> %100 Duty Cycle /\ 0x00 -> %0 Duty Cycle
if (result != RESULT_OK) return result;
return result;
}
generalStatus_t getGeneralStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
uint8_t buf[2];
uint8_t DeviceAddress;
DeviceAddress = DeviceAddress | address;
resultConditions_t result;
buf[0] = Daddress->Fields.FanStatusRegisterAddress;
generalStatus_t returnValue = NO_ERROR;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf+1,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
if (buf[0] == 0x00){
return returnValue;
}
else {
if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000){
returnValue = DRIVE_FAIL_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b01000000) == (uint8_t)0b01000000){
returnValue = FAN_SPIN_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000)
{
returnValue = FAN_STALL_ERROR;
return returnValue;
}
else{
returnValue = UNEXPECTED_ERROR;
return returnValue;
}
}
}
specialFanStallStatus_t getStallStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
uint8_t buf[2];
uint8_t DeviceAddress;
DeviceAddress = DeviceAddress | address;
resultConditions_t result;
buf[0] = Daddress->Fields.FanStallRegisterAddress;
specialFanStallStatus_t returnValue = NO_ERROR;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
if (buf[0] == 0x00){
return returnValue;
}
else {
if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
returnValue = FAN_1_STALL_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
returnValue = FAN_2_STALL_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000)
{
returnValue = FAN_3_STALL_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b00010000) == (uint8_t)0b000100000)
{
returnValue = FAN_4_STALL_ERROR;
return returnValue;
}
else{
returnValue = UNEXPECTED_ERROR;
return returnValue;
}
}
}
specialFanSpinStatus_t getSpinStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
uint8_t buf[2];
uint8_t DeviceAddress;
DeviceAddress = DeviceAddress | address;
resultConditions_t result;
buf[0] = Daddress->Fields.FanSpinRegisterAddress;
specialFanSpinStatus_t returnValue = NO_SPIN_ERROR;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
if (buf[0] == 0x00){
return returnValue;
}
else {
if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
returnValue = FAN_1_SPIN_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
returnValue = FAN_2_SPIN_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000)
{
returnValue = FAN_3_SPIN_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b00010000) == (uint8_t)0b000100000)
{
returnValue = FAN_4_SPIN_ERROR;
return returnValue;
}
else{
returnValue = UNEXPECTED_ERROR;
return returnValue;
}
}
}
specialFanDriveStatus_t getDriveStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address){
uint8_t buf[2];
uint8_t DeviceAddress;
DeviceAddress = DeviceAddress | address;
resultConditions_t result;
buf[0] = Daddress->Fields.DriveFailStatusAddress;
specialFanDriveStatus_t returnValue = NO_ERROR;
result = HAL_SMBUS_Master_Transmit_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
result = HAL_SMBUS_Master_Receive_IT(hsmbus, DeviceAddress,buf,1,SMBUS_FIRST_AND_LAST_FRAME_NO_PEC);
if (result == RESULT_ERROR) return UNEXPECTED_ERROR;
if (buf[0] == 0x00){
return returnValue;
}
else {
if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
returnValue = FAN_1_DRIVE_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b10000000) == (uint8_t)0b10000000){
returnValue = FAN_2_DRIVE_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b00100000) == (uint8_t)0b00100000)
{
returnValue = FAN_3_DRIVE_ERROR;
return returnValue;
}
else if ((buf[0] & (uint8_t)0b00010000) == (uint8_t)0b000100000)
{
returnValue = FAN_4_DRIVE_ERROR;
return returnValue;
}
else{
returnValue = UNEXPECTED_ERROR;
return returnValue;
}
}
}
H file
#ifndef smbusDriver
#define smbusDriver
#ifdef __cplusplus
extern "C" {
#endif
#include "smbusDriver.h"
#include "stm32f0xx_hal_smbus.h"
#include "stm32f0xx_hal.h"
typedef union {
struct{
uint8_t configurationRegisterAddress;
uint8_t FanStatusRegisterAddress;
uint8_t FanStallRegisterAddress;
uint8_t FanSpinRegisterAddress;
uint8_t DriveFailStatusAddress;
uint8_t FanInterruptEnableRegisterAddress;
uint8_t PwmPolarityRegisterAddress;
uint8_t PwmOutputTypeRegisterAddress;
uint8_t PwmFrequency45Address;
uint8_t PwmFrequency123Address;
uint8_t PwmDivider1Address;
uint8_t PwmDivider2Address;
uint8_t PwmDivider3Address;
uint8_t PwmDivider4Address;
uint8_t PwmSettingAddress1;
uint8_t PwmSettingAddress2;
uint8_t PwmSettingAddress3;
uint8_t PwmSettingAddress4;
}Fields;
}addressValues_t;
typedef enum{
NO_ERROR,
DRIVE_FAIL_ERROR, // indicate that one or more fan could not be driven (ProgrammingError)
FAN_SPIN_ERROR, // indicate that one or more fan spin
FAN_STALL_ERROR, // indicate that one or more fan is stuck
UNEXPECTED_ERROR
} generalStatus_t;
typedef enum {
NO_STALL_ERROR,
FAN_5_STALL_ERROR,
FAN_4_STALL_ERROR,
FAN_3_STALL_ERROR,
FAN_2_STALL_ERROR,
FAN_1_STALL_ERROR,
UNEXPECTED_STALL_ERROR
} specialFanStallStatus_t;
typedef enum {
NO_SPIN_ERROR,
FAN_5_SPIN_ERROR,
FAN_4_SPIN_ERROR,
FAN_3_SPIN_ERROR,
FAN_2_SPIN_ERROR,
FAN_1_SPIN_ERROR,
UNEXPECTED_SPIN_ERROR
} specialFanSpinStatus_t;
typedef enum {
NO_DRIVE_ERROR,
FAN_5_DRIVE_ERROR,
FAN_4_DRIVE_ERROR,
FAN_3_DRIVE_ERROR,
FAN_2_DRIVE_ERROR,
FAN_1_DRIVE_ERROR,
UNEXPECTED_DRIVE_ERROR
} specialFanDriveStatus_t;
typedef enum{
RESULT_OK,
RESULT_ERROR,
RESULT_TIMEOUT,
RESULT_BUSY,
RESULT_INVALID,
} resultConditions_t;
typedef union {
struct {
uint8_t USECK : 1; // 1 => External Clock & 0 => Internal Clock
uint8_t DRECK : 1; // 1 => Clock pin output and push-pull driver 0 => Clock pin input
uint8_t reserved : 3;
uint8_t WD_EN : 1; // 1 => Watch clock is activated 0 => 0 watch clock is deactivated.
uint8_t DIS_TO : 1; // 1 => I2C is compatible 0 => SMBus time-out is enabled
uint8_t MASK : 1; // 1 => Alert is deactivated 0 => Alert is activated
} Fields;
uint8_t value;
} configuration_t;
typedef union {
struct
{
uint8_t FNSTL : 1; // stall error <=> 1
uint8_t FNSPIN : 1; // Spin up error <=> 1
uint8_t DVFAIL : 1; // Maximum speed PWM error <=> 1
uint8_t reserved : 5;
}Fields;
uint8_t value;
}FanStatusRegister_t;
typedef union {
struct {
uint8_t F1STL : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
uint8_t F2STL : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
uint8_t F3STL : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
uint8_t F4STL : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
uint8_t F5STL : 1; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
uint8_t reserved : 3; // tachometer count has exceeded maximum valid TACH count, initializing stall <=> 1
} Fields;
uint8_t value;
} FanStallStatusRegister_t;
typedef union {
struct {
uint8_t F1SPIN : 1; // spin start error <=> 1
uint8_t F2SPIN : 1; // spin start error <=> 1
uint8_t F3SPIN : 1; // spin start error <=> 1
uint8_t F4SPIN : 1; // spin start error <=> 1
uint8_t F5SPIN : 1; // spin start error <=> 1
uint8_t reserved : 3; // spin start error <=> 1
} Fields;
uint8_t value;
}FanSpinStatusRegister_t;
typedef union {
struct{
uint8_t DRVF1 : 1; // rpm error <=> 1
uint8_t DRVF2 : 1; // rpm error <=> 1
uint8_t DRVF3 : 1; // rpm error <=> 1
uint8_t DRVF4 : 1; // rpm error <=> 1
uint8_t DRVF5 : 1; // rpm error <=> 1
uint8_t reserved : 3; // rpm error <=> 1
}Fields;
uint8_t value;
} DriveFailStatus_t;
typedef union {
struct {
uint8_t F1ITEN : 1; // Alert Fan 1 enable <=> 1
uint8_t F2ITEN : 1; // Alert Fan 2 enable <=> 1
uint8_t F3ITEN : 1; // Alert Fan 3 enable <=> 1
uint8_t F4ITEN : 1; // Alert Fan 4 enable <=> 1
uint8_t F5ITEN : 1; // Alert Fan 5 enable <=> 1
uint8_t reserved : 3;
}Fields;
uint8_t value;
}FanInterruptEnableRegister_t;
typedef union {
struct {
uint8_t PLRITY1 : 1; // FFh produce 100% duty cycle <=> 1
uint8_t PLRITY2 : 1; // FFh produce 100% duty cycle <=> 1
uint8_t PLRITY3 : 1; // FFh produce 100% duty cycle <=> 1
uint8_t PLRITY4 : 1; // FFh produce 100% duty cycle <=> 1
uint8_t PLRITY5 : 1; // FFh produce 100% duty cycle <=> 1
uint8_t reserved : 3;
}Fields;
uint8_t value;
}PwmPolarityRegister_t;
typedef union {
struct {
uint8_t PMOT1 : 1; // OpenDrain <=> 0 and PullPush output <=> 1
uint8_t PMOT2 : 1; // OpenDrain <=> 0 and PullPush output <=> 1
uint8_t PMOT3 : 1; // OpenDrain <=> 0 and PullPush output <=> 1
uint8_t PMOT4 : 1; // OpenDrain <=> 0 and PullPush output <=> 1
uint8_t PMOT5 : 1; // OpenDrain <=> 0 and PullPush output <=> 1
uint8_t reserved : 3;
} Fields;
uint8_t value;
} PwmOutputTypeRegister_t;
typedef union {
struct {
uint8_t PwmFrequency4 : 2;
uint8_t PwmFrequency5 : 2;
uint8_t reserved : 4;
}Fields;
uint8_t value;
}PwmFrequency45_t;
typedef union {
struct {
uint8_t PwmFrequency1 : 2;
uint8_t PwmFrequency2 : 2;
uint8_t PwmFrequency3 : 2;
uint8_t reserved : 2;
}Fields;
uint8_t value;
}PwmFrequency123_t;
typedef union {
struct {
uint8_t DriveSetting_1: 8;
uint8_t DriveSetting_2: 8;
uint8_t DriveSetting_3: 8;
uint8_t DriveSetting_4: 8;
}Fields;
uint32_t value;
}CurrentDriveSettings_t;
typedef union {
struct{
uint8_t pwmDivider_1 :8;
uint8_t pwmDivider_2 :8;
uint8_t pwmDivider_3 :8;
uint8_t pwmDivider_4 :8;
}Fields;
uint32_t value;
}PwmDividerRegister_t;
typedef union{
struct {
uint8_t pwmSettings1 :8;
uint8_t pwmSettings2 :8;
uint8_t pwmSettings3 :8;
uint8_t pwmSettings4 :8;
}Fields;
}PwmSettings_t;
resultConditions_t InitializeDriver(SMBUS_HandleTypeDef *hsmbus, uint8_t address, addressValues_t *Daddress);
resultConditions_t setPwmConfig(uint8_t Pwm, addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address);
generalStatus_t getGeneralStatus(addressValues_t *Daddress,SMBUS_HandleTypeDef *hsmbus, uint8_t address);
#endif
Datasheet: https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/EMC2301-2-3-5-Data-Sheet-DS20006532A.pdf
Estimation whether code is working or not

Firstly, I would recommend that you use STM's library AN4502.
The difference between the master and the slave is the same as for the i2c bus. All bus transfers are initialized by the master.
I think there is not emulator of EMC2301. But to test the bus you can use examples from the STM AN4502.
Your code won't work because the HAL_SMBUS_Master_Transmit_IT and HAL_SMBUS_Master_Receive_IT functions are called asynchronously and require you to wait for the execution to finish when you call two functions in a row, you will get the result HAL_BUSY. Use the library AN4502, it will make it easier to interact with the peripheral.

Related

Binary search loop is not breaking when the search element input is not prsenting in the sorted array

I am implementing the binary search in C as below, but when I'm passing the element which is not available in the sorted array, the code is enter into infinite loop since the midelement is repetitively calculating the same value (midelement is 4, and then start index becomes 5 (elementtofind > InputArray[midelement]), end index is 4, hence again returns the mid element as 4) after the 9th iteration of the loop, can anyone find how could I improve this logic.
#define MAX_NUM_INPUT (358U)
uint16 InputArray[MAX_NUM_INPUT] = {0x0103, 0x0104, 0x0109, 0x010A, 0x0133, 0x0180, 0x181, 0x183,.....upto 358 elements};
int main()
{
boolean elmntFound = 0;
uint16 elmntTofnd = 0x0134;
elmntFound = SearchPassedElement(0, MAX_NUM_INPUT, elmntTofnd);
if(elmntFound == 0)
{
printf("elementfound");
}
else
{
printf("elementNOTfound");
}
}
static boolean SearchPassedElement (uint16 FrstElmntIdx,uint16 LstElmntIdx, uint16 ElmntToFind)
{
boolean ReturnValue = 1;
uint16 startIdx = FrstElmntIdx;
uint16 endIdx = LstElmntIdx;
uint16 loc_midElmntIdx;
boolean OperationStatus = FALSE;
if(LstElmntIdx >= FrstElmntIdx)
{
while (OperationStatus == FALSE)
{
loc_midElmntIdx = (startIdx + endIdx) / 2U ;
if (ElmntToFind == InputArray[loc_midElmntIdx])
{
OperationStatus = TRUE;
ReturnValue = 0 ;
}
else if (ElmntToFind > InputArray[loc_midElmntIdx])
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
startIdx = loc_midElmntIdx + 1U;
}
}
else
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
endIdx = loc_midElmIdx - 1U ;
}
}
}
}
else
{
loopCntr = 0;
/* Incorrect input arguments */
ReturnValue = 1;
}
return ReturnValue;
}
I have found one logic as if the midelemnt is returned with same value for more than 3 times the lop shall be breaked, and evaluating the same.
static boolean SearchPassedElement (uint16 FrstElmntIdx,uint16 LstElmntIdx, uint16 ElmntToFind)
{
boolean ReturnValue = 1;
uint16 startIdx = FrstElmntIdx;
uint16 endIdx = LstElmntIdx;
uint16 loc_midElmntIdx;
boolean OperationStatus = FALSE;
uint16 prev_loc_midElmIdx = 0;
uint16 is_midElmIdxSame_count = 0;
if(LstElmntIdx >= FrstElmntIdx)
{
while (OperationStatus == FALSE)
{
loc_midElmntIdx = (startIdx + endIdx) / 2U ;
if (ElmntToFind == InputArray[loc_midElmntIdx])
{
OperationStatus = TRUE;
ReturnValue = 0 ;
}
else if (ElmntToFind > InputArray[loc_midElmntIdx])
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
startIdx = loc_midElmntIdx + 1U;
}
}
else
{
/* if entire array was already checked*/
if (startIdx == endIdx)
{
OperationStatus = TRUE;
ReturnValue = 1 ;
}
else /* othewise, */
{
endIdx = loc_midElmIdx - 1U ;
}
}
if(prev_loc_midElmIdx != loc_midElmIdx)
{
prev_loc_midElmIdx = loc_midElmIdx;
}
else
{
is_midElmIdxSame_count++;
/*as the divisor is 2 the same value can't return more that 2 times, hence if the same value is return more than
* 2 times the loop should be braked
*/
if(is_midElmIdxSame_count == 3)
{
elmntNotFnd = 3;
/* Stop operation and return failure*/
OperationStatus = TRUE;
ReturnValue = 1 ;
}
}
}
}
else
{
loopCntr = 0;
/* Incorrect input arguments */
ReturnValue = 1;
}
return ReturnValue;
}
There's no such type called boolean in C. You have to #include <stdbool.h> to use the bool type. The same thing for uint16, you have to #include <stdint.h> and use uint16_t.
And your code is very complicated. You needlessly use a lot of variables to get one simple thing done.
Here is a more compact version:
bool binary_search(size_t start, size_t end, const uint16_t elem, const uint16_t array[])
{
while (start < end) {
size_t middle = (start + end) / 2;
if (elem == array[middle])
return true;
if (elem < array[middle])
end = middle;
else
start = middle + 1;
}
return false;
}
It returns true if the element is found, false otherwise.
Example:
int main(void)
{
uint16_t array[] = {1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U};
const size_t size = sizeof array / sizeof array[0];
const uint16_t elem = 10U;
printf("%s\n", binary_search(0, size, elem, array) ? "Found" : "Not found");
}
Found
Few things to note:
size_t is the appropriate type for indexing arrays.
Use const (i.e. read-only) when you don't modify your variables.
Don't write C in Pascal style.

How can I reduce the size of my code and get the same result

Is there a way to get the same result with a smaller size of code in c?
My Function:
void PCA9575_set_gpio_level(uint8_t gpio_num, uint8_t level) {
uint8_t reg, data, pin;
uint8_t buf[1] = {0};
buf[1] = PCA9575_read_register(OUT0);
if (gpio_num >= 28 && gpio_num <= 35) {
reg = OUT0;
pin = gpio_num - 27;
if (pin == 3) {
pin = 4;
} else if (pin == 4) {
pin = 8;
} else if (pin == 5) {
pin = 16;
} else if (pin == 6) {
pin = 32;
} else if (pin == 7) {
pin = 64;
} else if (pin == 8) {
pin = 128;
} else {
return;
}
if (level == 1) {
if (buf[1] == 0) {
data = pin;
} else if (buf[1] == 0xFF) {
data = 0xFF;
} else {
data = buf[1] ^ pin;
}
} else if (level == 0) {
if (buf[1] == 0) {
data = 0;
} else {
data = buf[1] ^ pin;
}
} else {
return;
}
}
else if (gpio_num >= 36 && gpio_num <= 43) {
reg = OUT1;
pin = gpio_num - 35;
if (pin == 3) {
pin = 4;
} else if (pin == 4) {
pin = 8;
} else if (pin == 5) {
pin = 16;
} else if (pin == 6) {
pin = 32;
} else if (pin == 7) {
pin = 64;
} else if (pin == 8) {
pin = 128;
} else {
return;
}
if (level == 1) {
if (buf[1] == 0) {
data = pin;
} else {
data = buf[1] ^ pin;
}
} else if (level == 0) {
if (buf[1] == 0) {
data = 0;
} else {
data = buf[1] ^ pin;
}
} else {
return;
}
}
else {
return;
}
PCA9575_write_to_register(reg, data);
}
The buf[1] variable is a value from 00000000 - 11111111 which is based on what has already been set.
The data variable is a value from 00000000 - 11111111 which will set the gpio pins.
The code should read what gpio pins are set and keep them set. Also at the same time set the new desired gpio pin.
GPIO pins are values from 28 - 43.
maybe:
void PCA9575_set_gpio_level(uint8_t gpio_num, uint8_t level)
{
uint8_t reg, pin;
uint8_t buf = PCA9575_read_register(OUT0);
if (gpio_num > 27 && gpio_num < 36)
{
reg = OUT0;
pin = gpio_num - 27;
}
else
{
if (gpio_num > 35 && gpio_num < 44)
{
reg = OUT1;
pin = gpio_num - 35;
}
}
else return;
pin = 1 << (pin - 1);
if(level < 2)
{
if(!buf) data = level * pin;
else if(buf == 0xff && gpio_num < 36) data = 0xff;
else data = buf ^pin;
}
PCA9575_write_to_register(reg, data);
}

CAN frame over MQTT (need to convert hex string to byte array)

I am implementing a MQTT communication. I want to send CAN frames over MQTT through a graphical interfaces (realized in python). I am able to send messages from the GUI to one topic and I am able to see messages arrived on the same topic (using paho library) when I use the board. The function is below and the topic is diagnostic_request/topic:
void onMessageArrived
(
const char* topic,
const uint8_t* payload,
size_t payloadLen,
void* context
)
{
//LE_FATAL("The publisher received a message!");
//GIMP
char payloadStr[payloadLen + 1];
memcpy(payloadStr, payload, payloadLen);
payloadStr[payloadLen] = '\0';
LE_INFO("Received message! topic: \"%s\", payload: \"%s\"", topic, payloadStr);
//GIMP principio di conversione
if (strcmp(subscribeTopic, topic)==0)
LE_INFO("Sei sul topic di richiesta diagnostica!");
can_send();
}
At this point I have a difficulty. My can_send function (that works!) is:
int can_send(void)
{
const char* subscribeTopic = "diagnostic_request/topic";
LE_FATAL_IF(
mqtt_Subscribe(MQTTSession, subscribeTopic, MQTT_QOS0_TRANSMIT_ONCE) != LE_OK,
"failed to subscribe to %s",
subscribeTopic);
LE_INFO("Subscribed to topic (%s)", subscribeTopic);
int nbytesWrite;
// USE SEND STANDARD FRAME
frameWrite.can_id = 0x750; //codice identificativo di una richiesta diagnostica per centralina simulata
frameWrite.can_id &= CAN_SFF_MASK;
frameWrite.can_dlc = 8;
//strcpy((char *)frameWrite.data, "MGATE");
frameWrite.data[0] = 0x03;
frameWrite.data[1] = 0x22;
frameWrite.data[2] = 0xF1;
frameWrite.data[3] = 0x89;
frameWrite.data[4] = 0x00;
frameWrite.data[5] = 0x00;
frameWrite.data[6] = 0x00;
frameWrite.data[7] = 0x00;
if ((nbytesWrite = write(sdw, &frameWrite, sizeof(frameWrite))) != sizeof(frameWrite))
{
canwrite = false;
LE_INFO ("Writing error, nbytesWrite = %d", nbytesWrite);
return SOCK_WRITING_ERROR;
}
canwrite = true;
return 0;
}
So I have to call can_send in the onMessageArrived function when is statement is ok. I am able to see when I send a publish on diagnostic_request/topic. The only problem is to send the payloadStr value to the can_send function and unpackage it in the frameWrite.data[]. Can someone help me to understand how to modify the can_send function in order that the values
frameWrite.data[0] = 0x03;
frameWrite.data[1] = 0x22;
frameWrite.data[2] = 0xF1;
frameWrite.data[3] = 0x89;
frameWrite.data[4] = 0x00;
frameWrite.data[5] = 0x00;
frameWrite.data[6] = 0x00;
frameWrite.data[7] = 0x00;
are values that I send through mqtt in the payloadStr? I send a string of 8 bytes but I can't unpackage it.
Any help will be appreciated
Regards
Taking the approach of "write the test first".....
int convertNybble (char const hex)
{
if (hex >= '0' && hex <= '9')
{
return hex - '0';
}
else if (hex >= 'a' && hex <= 'f')
{
return 10 + (hex - 'a');
}
else if (hex >= 'A' && hex <= 'F')
{
return 10 + (hex - 'A');
}
return -1; // invalid hex character
}
#define ERR_NOT_EVEN_NUMBER_OF_DIGITS -1
#define ERR_STRING_TOO_LONG -2
#define ERR_INVALID_CHAR -3
int preparePayload(char const* hexString, unsigned char* canBuffer, size_t const bufLen)
{
size_t hexLen = strlen(hexString);
if (0 != (hexLen % 2))
{
// Expect an even number of digits.
return ERR_NOT_EVEN_NUMBER_OF_DIGITS;
}
size_t payloadLen = hexLen / 2;
// buffer will contain payload-length, followed by payload data.
// so payloadLen+1 must be able to fit into bufLen - fail if payloadLen+1 > bufLen, which is the same as payloadLen >= bufLen
if (payloadLen >= bufLen)
{
// will not be able to fit the decoded string into the payload buffer
return ERR_STRING_TOO_LONG;
}
unsigned char* bufEnd = canBuffer;
bufEnd += bufLen;
*canBuffer++ = (unsigned char)payloadLen;
while (payloadLen > 0)
{
payloadLen--;
int hexDigit[2];
hexDigit[0] = convertNybble(*hexString++);
hexDigit[1] = convertNybble(*hexString++);
if ((hexDigit[0] < 0) || (hexDigit[1] < 0))
{
return ERR_INVALID_CHAR;
}
*canBuffer++ = (hexDigit[0] << 4) | hexDigit[1];
}
// fill any leftovers with zero
while (canBuffer < bufEnd)
{
*canBuffer++ = 0;
}
return (0);
}
int performTests()
{
char const* testStr[5] =
{
"12345",
"0123456789ABCDEF",
"#ABC",
"0AF9",
"0123456789ABCD"
};
#define MARKER 0xFF
#define PAYLOAD_LEN 8
unsigned char payload[PAYLOAD_LEN+1];
payload[PAYLOAD_LEN] = MARKER;
int decodeResult = preparePayload(testStr[0], payload, PAYLOAD_LEN);
if (ERR_NOT_EVEN_NUMBER_OF_DIGITS != decodeResult) { return -1; } //not expected result
decodeResult = preparePayload(testStr[1], payload, PAYLOAD_LEN);
if (ERR_STRING_TOO_LONG != decodeResult) { return -1; }
decodeResult = preparePayload(testStr[2], payload, PAYLOAD_LEN);
if (ERR_INVALID_CHAR != decodeResult) { return -1; }
// here we are checking the character decoding
decodeResult = preparePayload(testStr[3], payload, PAYLOAD_LEN);
if (0 != decodeResult) { return -1; }
if (payload[0] != 2) { return -1; }
if (payload[1] != 0x0A) { return -1; }
if (payload[2] != 0xF9) { return -1; }
if (payload[3] != 0) { return -1; }
if (payload[7] != 0) { return -1; }
// payload contains - 02 0a f9 00 00 00 00 00 00
// here we are checking the limit of the payload capacity
decodeResult = preparePayload(testStr[4], payload, PAYLOAD_LEN);
if (0 != decodeResult) { return -1; }
// payload contains - 07 01 23 45 67 89 ab cd
// check we haven't overrun the buffer
if (payload[8] != MARKER) { return -1; }
// all tests pass
return 0;
}
int main()
{
int testResult = performTests();
return testResult;
}
You can then embody the decoder as follows:
convertNybble, preparePayload etc as above....
int canbusSend(unsigned char const* canbusPayload)
{
//etc
// - copy payloadBytes to frameWrite.data....
//etc
}
void onMessageArrived
(
const char* topic,
const uint8_t* mqttPayload,
size_t payloadLen,
void* context
)
{
#define CANBUS_PAYLOAD_BUFFER_LEN 8
unsigned char canbusPayload[CANBUS_PAYLOAD_BUFFER_LEN];
int decodeResult = preparePayload((char const*)mqttPayload, canbusPayload, CANBUS_PAYLOAD_BUFFER_LEN);
if (0 == decodeResult)
{
int canbusSendResult = canbusSend(canbusPayload);
// TODO : report error if failed
}
else
{
//TODO : report error
}
}

I'm trying to make a morse code transmitter with the AtMega 32u4, but the microprocessor dosen't sees my input buttons and i don't know why?

I have an Adafruit feather 32u4 LoRa transmitter, I want to make a digital Morse transmitter, I took the transmission code from the internet and decided to write my own code for the rest. The two transistors transmit to each other but the micro don sees my input buttons.
int StatoPrecP2 = 0;
int i;
char SendData;
void loop()
{
switch (Stato) {
StatoAttP1 = digitalRead(P_Riga);
StatoAttP2 = digitalRead (P_Punto);
case 0:
if (StatoAttP1 == 1) /*&& (StatoPrecP1 != StatoAttP1 )) */{
digitalWrite(ButtonRecived, HIGH);
delay (250);
digitalWrite(ButtonRecived, LOW);
Stato = 1;
SendData = ".";
}
if ((StatoAttP2 == 1) && (StatoPrecP2 != StatoAttP1)) {
digitalWrite(ButtonRecived, 1);
delay (250);
digitalWrite(ButtonRecived, 0);
Stato = 1;
SendData = "-";
}
if (rf95.available())
{
// Should be a message for us now
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len))
{
digitalWrite(LED, HIGH);
RH_RF95::printBuffer("Received: ", buf, len);
Serial.print("Got: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC);
if (*buf = ".") {
PORTF = PORTF | 0x20;
delay(1000);
PORTF = PORTF & ~0x20;
}
else if (*buf = "-") {
PORTF = PORTF | 0x20;
delay(2500);
PORTF = PORTF & ~0x20;
}
}
else
{
Serial.println("Receive failed");
}
case 1:
// Send a reply
for (i = 0; i < 5000; i++) {
uint8_t data = SendData;
rf95.send(data, sizeof(data));
rf95.waitPacketSent();
Serial.println("Sent a reply");
digitalWrite(LED, LOW);
if ((StatoAttP1 = 1) & (StatoAttP1 != StatoPrecP1)) {
PORTF = PORTF | 0x10;
delay (250);
PORTF = PORTF & ~0x10;
Stato = 1;
uint8_t data[] = ".";
i = 0;
}
else if ((StatoAttP2 = 1) & (StatoAttP2 != StatoPrecP2)) {
PORTF = PORTF | 0x10;
delay (250);
PORTF = PORTF & ~0x10;
Stato = 1;
uint8_t data[] = "-";
i = 0;
}
delay (1);
}
Stato = 0;
}
}
StatoPrecP1 = StatoAttP1;
StatoPrecP2 = StatoAttP2;
}
While it's allowed to put statements inside a switch that still are outside any case, those will simply not be executed.
You have:
switch (Stato) {
StatoAttP1 = digitalRead(P_Riga);
StatoAttP2 = digitalRead (P_Punto);
case 0:
But the two digitalRead calls will never happen, which is the source of your problem.
You need to place those statements outside the switch:
StatoAttP1 = digitalRead(P_Riga);
StatoAttP2 = digitalRead (P_Punto);
switch (Stato) {
case 0:
A decent compiler should be able to warn about this problem, and if not you need to enable more warnings. And you should treat those warnings as errors the must be fixed.

TERMIOS C Program to communicate with STM32F103 µC

I am on stm32f103c8t6 with STDP-Lib, using stm32's usb library for virtual com port and wanna to talk with the µC via termios-Pc-program. The termios program can read the data the chip is sending via USB, but when I wanna answer, the chip is not reacting on the data I send. What am I doing wrong when sending?
The termios-program:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
typedef union {
int num;
char part[2];
} _16to8;
static void sendData(int tty, unsigned char c) {
write(tty, &c, 1);
}
static unsigned char readData(int tty) {
unsigned char c;
while(read(tty, &c, 1) <= 0);
return c;
}
static unsigned char* readALotOfData(int tty, int len) {
unsigned char* c = NULL;
c = calloc(len, sizeof(unsigned char));
for(int i = 0; i < len; i++) {
c[i] = readData(tty);
}
return c;
}
static void sendCmd(int tty, char* c, size_t len) {
unsigned char* a = NULL;
int i = 0;
a = calloc(len, sizeof(unsigned char));
memcpy(a, c, len);
for(; i < len; i++) {
sendData(tty, a[i]);
}
free(a);
a = NULL;
}
int main(int argc, char** argv) {
struct termios tio;
int tty_fd;
FILE* fd;
struct stat st;
unsigned char c;
unsigned char* buf = NULL;
buf = calloc(4096, sizeof(unsigned char));
memset(&tio, 0, sizeof(tio));
tio.c_cflag = CS8;
tty_fd = open(argv[1], O_RDWR | O_NONBLOCK);
if(tty_fd == -1) {
printf("failed to open port\n");
return 1;
}
char mode;
if(!strcmp(argv[2], "flash")) {
mode = 1;
fd = fopen(argv[3], "r");
if(fd == NULL) {
printf("failed to open file\n");
return 1;
}
} else if(!strcmp(argv[2], "erase")) {
mode = 0;
} else {
printf("unknown operation mode\n");
return 1;
}
cfsetospeed(&tio, B115200);
cfsetispeed(&tio, B115200);
tcsetattr(tty_fd, TCSANOW, &tio);
unsigned char* id = readALotOfData(tty_fd, 20);
printf("%s\n", id);
if(strstr((const char*)id, "1234AABBCC1234")) {
sendCmd(tty_fd, "4321CCBBAA4321", 14);
printf("id verified\n");
} else {
printf("Could not identify device\n");
return 1;
}
if(mode) {
printf("going to flash the device\n");
sendCmd(tty_fd, "\xF1\xA5", 2);
stat(argv[3], &st);
int siz = st.st_size;
char sizR[2] = "\0";
sizR[1] = (unsigned char)(siz & 0xFF);
sizR[0] = (unsigned char)(siz >> 8);
_16to8 num = {0};
num.part[0] = sizR[0];
num.part[1] = sizR[1];
sendCmd(tty_fd, (char*)&num.num, 2);
char buffer[2] = {0};
int i = 0;
while(fread(&buffer, 1, 4, fd)) {
// sendCmd(tty_fd, buffer, 4);
// printf("%s\n", readALotOfData(tty_fd, 5));
}
} else {
printf("going to erase the device's memory\n");
sendCmd(tty_fd, (char*)0xE2A5, 2);
}
close(tty_fd);
return 0;
}
µCProgram:
#include "stm32f10x_conf.h"
#include "main.h"
void eraseFlashPage(uint8_t page) {
uint32_t addr = FLASH_ADDR + 0x400 * page;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR | FLASH_FLAG_EOP);
FLASH_ErasePage(addr);
FLASH_Lock();
}
void writeFlashAddr(uint8_t page, uint16_t offset, uint32_t data) {
uint32_t addr = FLASH_ADDR + 0x400 * page + offset;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR | FLASH_FLAG_EOP);
FLASH_ProgramWord(addr, (uint32_t)data);
FLASH_Lock();
}
uint32_t readFlashAddr(uint8_t page) {
uint32_t addr = FLASH_ADDR + 0x400 * page;
return *(uint32_t*)addr;
}
void TIM2_IRQHandler() {
static int count = 0;
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if(mode) {
if(count == 2) {
count = 0;
GPIO_ToggleBits(GPIOA, GPIO_Pin_15);
}
count++;
} else {
GPIO_ToggleBits(GPIOA, GPIO_Pin_15);
}
}
}
int main() {
Set_System();
Set_USBClock();
USB_Interrupts_Config();
USB_Init();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitTypeDef gpioStruct;
gpioStruct.GPIO_Pin = GPIO_Pin_15;
gpioStruct.GPIO_Mode = GPIO_Mode_Out_PP;
gpioStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpioStruct);
GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 200Hz -> 8Hz
TIM_TimeBaseInitTypeDef timStruct;
timStruct.TIM_Prescaler = 60000;
timStruct.TIM_CounterMode = TIM_CounterMode_Up;
timStruct.TIM_Period = 50; // ISR at 0.125s
timStruct.TIM_ClockDivision = TIM_CKD_DIV4;
timStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &timStruct);
TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_InitTypeDef nvicStruct;
nvicStruct.NVIC_IRQChannel = TIM2_IRQn;
nvicStruct.NVIC_IRQChannelPreemptionPriority = 0;
nvicStruct.NVIC_IRQChannelSubPriority = 1;
nvicStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvicStruct);
_delay_ms(500);
while(1) {
mode = 0;
Receive_length = 0;
char bootID[64];
for(volatile uint32_t cnt = 0; cnt < 4800 * 5000 / 4 / 25; cnt++) {
_printf("1234AABBCC1234");
CDC_Receive_DATA();
if(Receive_length >= 14) {
_gets((char*)&bootID, 14);
if(!memcmp(bootID, "4321CCBBAA4321", 14)) {
mode = 1;
break;
}
Receive_length = 0;
}
}
if(mode) {
uint32_t opt = 0;
_printf("operating mode?\n"); //debug
_gets((char*)&opt, 2);
if(opt == 0xF1A5) {
uint32_t len = 0;
uint32_t data = 0;
uint16_t i = 0;
_gets((char*)&len, 2);
_printf("writing %d/%d bytes starting at 0x%x\n", len, (117 - START_PAGE) * 1024, FLASH_ADDR); // debug
if(len < (117 - START_PAGE) * 1024) { // 117 or 64?
_printf("start writing to flash\n"); //debug
for(i = 0; i <= len / 1024; i++) {
eraseFlashPage(i);
_printf("erasing page %d\n", i); //debug
}
for(i = 0; i < len; i += 4) {
uint8_t page = i / 1024;
_printf("i:%d page:%d offset:%d\n", i, page, i - page * 1024); // debug
_gets((char*)&data, 4);
writeFlashAddr(page, i - page * 1024, data);
_printf("Page %d and 0x%x\n", page, FLASH_ADDR + 0x400 * page + i - page * 1024); // debug
}
_printf("done\n"); //debug
uint32_t sp = *(uint32_t*) FLASH_ADDR;
if((sp & 0x2FFF0000) == 0x20000000) {
TIM_Cmd(TIM2, DISABLE);
GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICER[1] = 0xFFFFFFFF;
NVIC->ICPR[0] = 0xFFFFFFFF;
NVIC->ICPR[1] = 0xFFFFFFFF;
PowerOff();
pFunction jmpUser;
uint32_t jmpAddr = *(__IO uint32_t*)(FLASH_ADDR + 4);
jmpUser = (pFunction)jmpAddr;
__set_MSP(*(__IO uint32_t*)FLASH_ADDR);
jmpUser();
}
} else {
_printf("not enought flash space available\n"); //debug
}
} else if(opt == 0xE2A5) {
for(int i = 0; i < (117 - START_PAGE); i++) {
eraseFlashPage(i);
_printf("erasing page %d\n", i); //debug
}
}
} else {
uint32_t sp = *(uint32_t*) FLASH_ADDR;
if((sp & 0x2FFF0000) == 0x20000000) {
TIM_Cmd(TIM2, DISABLE);
GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_RESET);
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICER[1] = 0xFFFFFFFF;
NVIC->ICPR[0] = 0xFFFFFFFF;
NVIC->ICPR[1] = 0xFFFFFFFF;
PowerOff();
pFunction jmpUser;
uint32_t jmpAddr = *(__IO uint32_t*)(FLASH_ADDR + 4);
jmpUser = (pFunction)jmpAddr;
__set_MSP(*(__IO uint32_t*)FLASH_ADDR);
jmpUser();
}
}
}
}
I want to send the identification string and then enter the operations.... A friend of me got a working program with serialport-lib usage, but I wanna use termios...
Anyone an idea why the controller is not reacting on the sent data?

Resources