ADD read and write wrapper function for i2c bus, start programming

procedure for si5351
This commit is contained in:
Tom Kuschel 2022-05-16 01:47:12 +02:00
parent 8f5cdc1f54
commit acc0f0a5da
4 changed files with 1162 additions and 13 deletions

View File

@ -81,7 +81,7 @@ extern "C" {
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include <stdint.h> #include <stdint.h>
#include <stm32_si5351_reg.h> /* register map of the Si5351 */
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
@ -89,14 +89,17 @@ extern "C" {
typedef struct __SI5351_HandleTypeDef *si5351_inst_t; typedef struct __SI5351_HandleTypeDef *si5351_inst_t;
/* Exported constants --------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/
/** @enum errno_t Error Number Constants /** @enum errno_t Error Number Constants, @TODO could also errno.h included!!
*/ */
typedef enum { typedef enum {
EPERM = 1, /*!< Operation not permitted */ EPERM = 1, /*!< Operation not permitted */
EIO = 5, /*!< I/O error */
ENOMEM = 12, /*!< Out of memory */ ENOMEM = 12, /*!< Out of memory */
ENODEV = 19, /*!< No such device */ ENODEV = 19, /*!< No such device */
EBUSY = 16, /*!< Device or resource busy */
EINVAL = 22, /*!< Invalid argument */ EINVAL = 22, /*!< Invalid argument */
EADDRINUSE = 98 /*!< Address already in use */ EADDRINUSE = 98,/*!< Address already in use */
ETIMEDOUT = 116 /*!< Connection timed out */
} si5351_errno_t; } si5351_errno_t;
/* Exported variables --------------------------------------------------------*/ /* Exported variables --------------------------------------------------------*/
@ -107,6 +110,7 @@ typedef enum {
si5351_inst_t si5351_init(void * i2c_handle, uint32_t xtal_frequency, uint8_t i2c_address); si5351_inst_t si5351_init(void * i2c_handle, uint32_t xtal_frequency, uint8_t i2c_address);
int si5351_deinit(si5351_inst_t si5351_handle); int si5351_deinit(si5351_inst_t si5351_handle);
int si5351_isready(si5351_inst_t inst); int si5351_isready(si5351_inst_t inst);
int si5351_program(si5351_inst_t inst);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

1081
Core/Inc/stm32_si5351_reg.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -101,7 +101,7 @@ void start_id_task(void *argument);
int main(void) int main(void)
{ {
/* USER CODE BEGIN 1 */ /* USER CODE BEGIN 1 */
int status = 0;
/* USER CODE END 1 */ /* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/ /* MCU Configuration--------------------------------------------------------*/
@ -142,6 +142,10 @@ int main(void)
printf("Device No. %d (Instance No: 0x%x) is %s\n", i, (unsigned int) instance_si5351[i], (ready==0) ? "ready" : "N/A"); printf("Device No. %d (Instance No: 0x%x) is %s\n", i, (unsigned int) instance_si5351[i], (ready==0) ? "ready" : "N/A");
} }
status = si5351_program(instance_si5351[1]);
printf("Device #1 gets status %d\n", status);
for (int i=2; i>=0; i--) { for (int i=2; i>=0; i--) {
si5351_deinit(instance_si5351[i]); si5351_deinit(instance_si5351[i]);
} }

View File

@ -23,12 +23,12 @@
*/ */
typedef struct __SI5351_HandleTypeDef { typedef struct __SI5351_HandleTypeDef {
void * i2c_handle; void * i2c_handle;
uint32_t xtal_frequency; /*!< XTAL or CLKIN frequency */
uint32_t xtal_frequency;
int si5351_num; int si5351_num;
struct __SI5351_HandleTypeDef *next; struct __SI5351_HandleTypeDef *next;
uint8_t i2c_address; uint8_t i2c_address; /*!< I2C address of the datasheet */
uint8_t initialized:1; // uint8_t interrupt_status_mask; /*!< Reg 2: Interrupt Status Mask */
uint8_t initialized:1; /*!< mark the driver initialized */
} si5351_HandleTypeDef; } si5351_HandleTypeDef;
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
@ -39,6 +39,34 @@ int si5351_errno = 0; /* error_number for functions whith return == NULL */
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/* wrapper function for receiving bytes from I2C bus
*/
static int si5351_error_status_i2c(HAL_StatusTypeDef status) {
switch (status) {
case HAL_TIMEOUT: return -ETIMEDOUT; break;
case HAL_ERROR: return -EIO; break;
case HAL_BUSY: return -EBUSY; break;
default: return 0;
}
}
int si5351_read(si5351_inst_t instance, uint8_t regaddr, uint8_t *data, uint16_t size) {
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read(instance->i2c_handle, instance->i2c_address<<1,
(uint16_t)regaddr, I2C_MEMADD_SIZE_8BIT, data, size, 0xffff);
return si5351_error_status_i2c(status);
}
int si5351_write(si5351_inst_t instance, uint8_t regaddr, uint8_t *data, uint16_t size) {
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Write(instance->i2c_handle, instance->i2c_address<<1,
(uint16_t)regaddr, I2C_MEMADD_SIZE_8BIT, data, size, 0xffff);
return si5351_error_status_i2c(status);
}
/** @brief Initialize the device Si5351 with the main parameters /** @brief Initialize the device Si5351 with the main parameters
* @param i2c_handle the handle of the I2C bus from HAL function, e.g. hi2c1 * @param i2c_handle the handle of the I2C bus from HAL function, e.g. hi2c1
* @param xtal_frequency either the XTAL frequency (25/27 MHz) or CLock-In * @param xtal_frequency either the XTAL frequency (25/27 MHz) or CLock-In
@ -56,10 +84,6 @@ si5351_HandleTypeDef *si5351_init(void * i2c_handle, uint32_t xtal_frequency, ui
return NULL; return NULL;
} }
#ifdef HAL_I2C_MODULE_ENABLED
#endif
si5351_handle = calloc(1, sizeof(*si5351_handle)); si5351_handle = calloc(1, sizeof(*si5351_handle));
if (si5351_handle == NULL) { if (si5351_handle == NULL) {
si5351_errno = ENOMEM; // cannot allocate any memory si5351_errno = ENOMEM; // cannot allocate any memory
@ -125,7 +149,7 @@ int si5351_deinit(si5351_HandleTypeDef * si5351_handle) {
return 0; return 0;
} }
/** @brief Check if there is the I2C device ready on the bus /** @brief Check if there is any I2C device ready on the bus
* @param si5351_instance Given si5351 device handle * @param si5351_instance Given si5351 device handle
* @return 0 on success (HAL_StatusTypeDef) * @return 0 on success (HAL_StatusTypeDef)
* @retval HAL_ERROR = 0x01 * @retval HAL_ERROR = 0x01
@ -144,6 +168,42 @@ int si5351_isready(si5351_inst_t inst) {
/* @TODO: create a pointer to that function for more flexiblity using other tools as HAL */ /* @TODO: create a pointer to that function for more flexiblity using other tools as HAL */
return status; return status;
} }
int si5351_program(si5351_inst_t inst) {
uint8_t data;
int status = 0;
if(!inst)
return -EINVAL;
do {
status = si5351_read(inst, SI5351_DEVICE_STATUS, &data, 1);
if (status)
return status;
} while(data & SI5351_SYS_INIT);
/* Disable Outputs Set CLKx_DIS high, Reg. 3 = 0xFF */
data = 0xff;
status = si5351_write(inst, SI5351_OUTPUT_ENABLE_CONTROL, &data, 1);
if (status)
return status;
/* power down all output drivers reg 16 -- 23 */
data = 0x80;
for(int i = SI5351_CLK0_CONTROL; i <= SI5351_CLK7_CONTROL; i++) {
status = si5351_write(inst, i, &data, 1);
if (status)
return status;
}
return 0;
}
#if 0 #if 0