diff --git a/targets/TARGET_STM/TARGET_STM32WL/TARGET_STM32WL55xC/TARGET_NUCLEO_WL55JC/PeripheralPins.c b/targets/TARGET_STM/TARGET_STM32WL/TARGET_STM32WL55xC/TARGET_NUCLEO_WL55JC/PeripheralPins.c index 85171e991e..cc8c6eed4d 100644 --- a/targets/TARGET_STM/TARGET_STM32WL/TARGET_STM32WL55xC/TARGET_NUCLEO_WL55JC/PeripheralPins.c +++ b/targets/TARGET_STM/TARGET_STM32WL/TARGET_STM32WL55xC/TARGET_NUCLEO_WL55JC/PeripheralPins.c @@ -55,11 +55,10 @@ MBED_WEAK const PinMap PinMap_ADC[] = { {NC, NC, 0} }; -// !!! SECTION TO BE CHECKED WITH DEVICE REFERENCE MANUAL MBED_WEAK const PinMap PinMap_ADC_Internal[] = { -// {ADC_TEMP, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)}, -// {ADC_VREF, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 17, 0)}, -// {ADC_VBAT, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 18, 0)}, + {ADC_TEMP, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, + {ADC_VREF, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 13, 0)}, + {ADC_VBAT, ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)}, {NC, NC, 0} }; diff --git a/targets/TARGET_STM/TARGET_STM32WL/analogin_device.c b/targets/TARGET_STM/TARGET_STM32WL/analogin_device.c index d97a5156bf..a6ff8be47c 100644 --- a/targets/TARGET_STM/TARGET_STM32WL/analogin_device.c +++ b/targets/TARGET_STM/TARGET_STM32WL/analogin_device.c @@ -19,30 +19,35 @@ #include "mbed_assert.h" #include "mbed_error.h" #include "mbed_debug.h" -#include "mbed_wait_api.h" #include "cmsis.h" #include "pinmap.h" #include "PeripheralPins.h" -void analogin_init(analogin_t *obj, PinName pin) + +#if STATIC_PINMAP_READY +#define ANALOGIN_INIT_DIRECT analogin_init_direct +void analogin_init_direct(analogin_t *obj, const PinMap *pinmap) +#else +#define ANALOGIN_INIT_DIRECT _analogin_init_direct +static void _analogin_init_direct(analogin_t *obj, const PinMap *pinmap) +#endif { - uint32_t function = (uint32_t)NC; + uint32_t function = (uint32_t)pinmap->function; + + // Get the peripheral name from the pin and assign it to the object + obj->handle.Instance = (ADC_TypeDef *)pinmap->peripheral; // ADC Internal Channels "pins" (Temperature, Vref, Vbat, ...) // are described in PinNames.h and PeripheralPins.c // Pin value must be between 0xF0 and 0xFF - if ((pin < 0xF0) || (pin >= 0x100)) { + if ((pinmap->pin < 0xF0) || (pinmap->pin >= 0x100)) { // Normal channels - // Get the peripheral name from the pin and assign it to the object - obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC); - // Get the functions (adc channel) from the pin and assign it to the object - function = pinmap_function(pin, PinMap_ADC); + // Configure GPIO - pinmap_pinout(pin, PinMap_ADC); + pin_function(pinmap->pin, pinmap->function); + pin_mode(pinmap->pin, PullNone); } else { // Internal channels - obj->handle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC_Internal); - function = pinmap_function(pin, PinMap_ADC_Internal); // No GPIO configuration for internal channels } MBED_ASSERT(obj->handle.Instance != (ADC_TypeDef *)NC); @@ -51,58 +56,77 @@ void analogin_init(analogin_t *obj, PinName pin) obj->channel = STM_PIN_CHANNEL(function); // Save pin number for the read function - obj->pin = pin; + obj->pin = pinmap->pin; // Configure ADC object structures obj->handle.State = HAL_ADC_STATE_RESET; - obj->handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; // Asynchronous clock mode, input ADC clock + obj->handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; obj->handle.Init.Resolution = ADC_RESOLUTION_12B; obj->handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; - obj->handle.Init.ScanConvMode = ADC_SCAN_DISABLE; // Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) - obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; // On STM32L1xx ADC, overrun detection is enabled only if EOC selection is set to each conversion (or transfer by DMA enabled, this is not the case in this example). + obj->handle.Init.ScanConvMode = ADC_SCAN_DISABLE; + obj->handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; obj->handle.Init.LowPowerAutoWait = DISABLE; - obj->handle.Init.ContinuousConvMode = DISABLE; // Continuous mode disabled to have only 1 conversion at each conversion trig - obj->handle.Init.NbrOfConversion = 1; // Parameter discarded because sequencer is disabled - obj->handle.Init.DiscontinuousConvMode = DISABLE; // Parameter discarded because sequencer is disabled - //obj->handle.Init.NbrOfDiscConversion = 1; // Parameter discarded because sequencer is disabled - obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; // Software start to trig the 1st conversion manually, without external event + obj->handle.Init.ContinuousConvMode = DISABLE; + obj->handle.Init.NbrOfConversion = 1; + obj->handle.Init.DiscontinuousConvMode = DISABLE; + obj->handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; obj->handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; obj->handle.Init.DMAContinuousRequests = DISABLE; - obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // DR register is overwritten with the last conversion result in case of overrun - obj->handle.Init.OversamplingMode = DISABLE; // No oversampling + obj->handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; + obj->handle.Init.LowPowerAutoPowerOff = DISABLE; + obj->handle.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_19CYCLES_5; + obj->handle.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5; + obj->handle.Init.OversamplingMode = DISABLE; + obj->handle.Init.Oversampling.Ratio = 0; // workaround + obj->handle.Init.Oversampling.RightBitShift = 0; // workaround + obj->handle.Init.Oversampling.TriggeredMode = 0; // workaround + obj->handle.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH; - // Enable ADC core clock + // Enable ADC clock + __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); __HAL_RCC_ADC_CLK_ENABLE(); - // Enable ADC conversion clock. - // Only necessary with asynchronous clock source - __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); - if (HAL_ADC_Init(&obj->handle) != HAL_OK) { - error("ADC initialization failed\r\n"); + error("Cannot initialize ADC"); } // ADC calibration is done only once - //if (!HAL_ADCEx_Calibration_GetValue(&obj->handle, ADC_SINGLE_ENDED)) { - // HAL_ADCEx_Calibration_Start(&obj->handle, ADC_SINGLE_ENDED); - //} + if (!HAL_ADCEx_Calibration_GetValue(&obj->handle)) { + if (HAL_ADCEx_Calibration_Start(&obj->handle) != HAL_OK) { + error("HAL_ADCEx_Calibration_Start error"); + } + } } +void analogin_init(analogin_t *obj, PinName pin) +{ + int peripheral; + int function; + + if ((pin < 0xF0) || (pin >= 0x100)) { + peripheral = (int)pinmap_peripheral(pin, PinMap_ADC); + function = (int)pinmap_find_function(pin, PinMap_ADC); + } else { + peripheral = (int)pinmap_peripheral(pin, PinMap_ADC_Internal); + function = (int)pinmap_find_function(pin, PinMap_ADC_Internal); + } + + const PinMap static_pinmap = {pin, peripheral, function}; + + ANALOGIN_INIT_DIRECT(obj, &static_pinmap); +} + + uint16_t adc_read(analogin_t *obj) { ADC_ChannelConfTypeDef sConfig = {0}; - // Configure ADC channel sConfig.Rank = ADC_REGULAR_RANK_1; - //sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5; - //sConfig.SingleDiff = ADC_SINGLE_ENDED; - //sConfig.OffsetNumber = ADC_OFFSET_NONE; - //sConfig.Offset = 0; + sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1; switch (obj->channel) { case 0: - sConfig.Channel = ADC_CHANNEL_VREFINT; - //sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // Minimum ADC sampling time when reading the internal reference voltage is 4us + sConfig.Channel = ADC_CHANNEL_0; break; case 1: sConfig.Channel = ADC_CHANNEL_1; @@ -138,55 +162,41 @@ uint16_t adc_read(analogin_t *obj) sConfig.Channel = ADC_CHANNEL_11; break; case 12: - sConfig.Channel = ADC_CHANNEL_12; + sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; + sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2; break; case 13: - sConfig.Channel = ADC_CHANNEL_13; + sConfig.Channel = ADC_CHANNEL_VREFINT; + sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2; break; case 14: - sConfig.Channel = ADC_CHANNEL_14; - break; - case 15: - sConfig.Channel = ADC_CHANNEL_15; - break; - case 16: - sConfig.Channel = ADC_CHANNEL_16; - break; - case 17: - sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; - //sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // Minimum ADC sampling time when reading the temperature is 5us - break; - case 18: sConfig.Channel = ADC_CHANNEL_VBAT; - //sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; // Minimum ADC sampling time when reading the VBAT is 12us + sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2; break; default: return 0; } if (HAL_ADC_ConfigChannel(&obj->handle, &sConfig) != HAL_OK) { - debug("ADC channel configuration failed\r\n"); + debug("HAL_ADC_ConfigChannel error\n"); } - // Start conversion if (HAL_ADC_Start(&obj->handle) != HAL_OK) { - debug("ADC start of conversion failed\r\n"); + debug("HAL_ADC_Start error\n"); } // Wait end of conversion and get value uint16_t adcValue = 0; - if (HAL_ADC_PollForConversion(&obj->handle, 10) == HAL_OK) { + if (HAL_ADC_PollForConversion(&obj->handle, 100) == HAL_OK) { adcValue = (uint16_t)HAL_ADC_GetValue(&obj->handle); } - if (HAL_ADC_Stop(&obj->handle) != HAL_OK) { - debug("HAL_ADC_Stop failed\r\n"); - } - LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE((&obj->handle)->Instance), LL_ADC_PATH_INTERNAL_NONE); + return adcValue; } + const PinMap *analogin_pinmap() { return PinMap_ADC; diff --git a/targets/TARGET_STM/TARGET_STM32WL/analogout_device.c b/targets/TARGET_STM/TARGET_STM32WL/analogout_device.c index ceed7e068a..01635aec5a 100644 --- a/targets/TARGET_STM/TARGET_STM32WL/analogout_device.c +++ b/targets/TARGET_STM/TARGET_STM32WL/analogout_device.c @@ -23,43 +23,88 @@ #include "mbed_error.h" #include "PeripheralPins.h" -DAC_HandleTypeDef hdac; +#if STATIC_PINMAP_READY +#define ANALOGOUT_INIT_DIRECT analogout_init_direct +void analogout_init_direct(dac_t *obj, const PinMap *pinmap) +#else +#define ANALOGOUT_INIT_DIRECT _analogout_init_direct +static void _analogout_init_direct(dac_t *obj, const PinMap *pinmap) +#endif +{ + DAC_ChannelConfTypeDef sConfig = {0}; + + // Get the peripheral name from the pin and assign it to the object + obj->dac = (DACName)pinmap->peripheral; + MBED_ASSERT(obj->dac != (DACName)NC); + + // Get the pin function and assign the used channel to the object + uint32_t function = (uint32_t)pinmap->function; + MBED_ASSERT(function != (uint32_t)NC); + + switch (STM_PIN_CHANNEL(function)) { + case 1: + obj->channel = DAC_CHANNEL_1; + break; + default: + error("Unknown DAC channel"); + break; + } + + // Configure GPIO + pin_function(pinmap->pin, pinmap->function); + pin_mode(pinmap->pin, PullNone); + + // Save the pin for future use + obj->pin = pinmap->pin; + + // Enable DAC clock + __HAL_RCC_DAC_CLK_ENABLE(); + + // Configure DAC + obj->handle.Instance = DAC; + obj->handle.State = HAL_DAC_STATE_RESET; + + if (HAL_DAC_Init(&obj->handle) != HAL_OK) { + error("HAL_DAC_Init failed"); + } + + sConfig.DAC_Trigger = DAC_TRIGGER_NONE; + sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; + sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY; + + sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; + + if (HAL_DAC_ConfigChannel(&obj->handle, &sConfig, obj->channel) != HAL_OK) { + error("Cannot configure DAC channel\n"); + } + + analogout_write_u16(obj, 0); +} void analogout_init(dac_t *obj, PinName pin) { + int peripheral = (int)pinmap_peripheral(pin, PinMap_DAC); + int function = (int)pinmap_find_function(pin, PinMap_DAC); - DAC_ChannelConfTypeDef sConfig = {0}; - - /* obj Initialization */ - obj->dac = (DACName)NC; - - obj->pin = pin; - - obj->channel = DAC_CHANNEL_1; + const PinMap static_pinmap = {pin, peripheral, function}; - /* DAC Initialization */ - hdac.Instance = DAC; - if (HAL_DAC_Init(&hdac) != HAL_OK) - { - //Error_Handler(); - } - /** DAC channel OUT1 config - */ - sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE; - sConfig.DAC_Trigger = DAC_TRIGGER_T1_TRGO; - sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; - sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE; - sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY; - - if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK) - { - //Error_Handler(); - } - + ANALOGOUT_INIT_DIRECT(obj, &static_pinmap); +} + +void analogout_free(dac_t *obj) +{ + __HAL_RCC_DAC_FORCE_RESET(); + __HAL_RCC_DAC_RELEASE_RESET(); + __HAL_RCC_DAC_CLK_DISABLE(); + + // Configure GPIO + pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); } const PinMap *analogout_pinmap() { return PinMap_DAC; } -#endif + +#endif // DEVICE_ANALOGOUT diff --git a/targets/TARGET_STM/TARGET_STM32WL/i2c_device.h b/targets/TARGET_STM/TARGET_STM32WL/i2c_device.h index e692164d8e..eedf470733 100644 --- a/targets/TARGET_STM/TARGET_STM32WL/i2c_device.h +++ b/targets/TARGET_STM/TARGET_STM32WL/i2c_device.h @@ -37,36 +37,20 @@ extern "C" { static inline uint32_t get_i2c_timing(int hz) { uint32_t tim = 0; - if (SystemCoreClock == 64000000) { - // Common settings: I2C clock = 64 MHz, Analog filter = ON, Digital filter coefficient = 0 - switch (hz) { - case 100000: - tim = 0x10707DBC; // Standard mode with Rise Time = 400ns and Fall Time = 100ns - break; - case 400000: - tim = 0x00602173; // Fast mode with Rise Time = 250ns and Fall Time = 100ns - break; - case 1000000: - tim = 0x00300B29; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns - break; - default: - break; - } - } else if (SystemCoreClock == 32000000) { - // Common settings: I2C clock = 32 MHz, Analog filter = ON, Digital filter coefficient = 0 - switch (hz) { - case 100000: - tim = 0x00707CBB; // Standard mode with Rise Time = 400ns and Fall Time = 100ns - break; - case 400000: - tim = 0x00300F38; // Fast mode with Rise Time = 250ns and Fall Time = 100ns - break; - case 1000000: - tim = 0x00100413; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns - break; - default: - break; - } + + // Common settings: I2C clock = 48 MHz, Analog filter = ON, Digital filter coefficient = 0 + switch (hz) { + case 100000: + tim = 0x20E03F53; // Standard mode with Rise Time = 640ns and Fall Time = 20ns + break; + case 400000: + tim = 0x20500817; // Fast mode with Rise Time = 250ns and Fall Time = 100ns + break; + case 1000000: + tim = 0x00500A18; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns + break; + default: + break; } return tim; } diff --git a/targets/TARGET_STM/i2c_api.c b/targets/TARGET_STM/i2c_api.c index 5634c7206c..98d5797b69 100644 --- a/targets/TARGET_STM/i2c_api.c +++ b/targets/TARGET_STM/i2c_api.c @@ -41,6 +41,7 @@ #include "PeripheralPins.h" #include "i2c_device.h" // family specific defines #include "mbed_error.h" +#include "platform/mbed_power_mgmt.h" #ifndef DEBUG_STDIO # define DEBUG_STDIO 0 @@ -294,6 +295,11 @@ void i2c_init_internal(i2c_t *obj, const i2c_pinmap_t *pinmap) // Configure I2C pins obj_s->event_i2cIRQ = I2C1_EV_IRQn; obj_s->error_i2cIRQ = I2C1_ER_IRQn; + +#if defined(TARGET_STM32WL) + /* In Stop2 mode, I2C1 and I2C2 instances are powered down (only I2C3 register content is kept) */ + sleep_manager_lock_deep_sleep(); +#endif } #endif #if defined I2C2_BASE @@ -303,6 +309,11 @@ void i2c_init_internal(i2c_t *obj, const i2c_pinmap_t *pinmap) __HAL_RCC_I2C2_CLK_ENABLE(); obj_s->event_i2cIRQ = I2C2_EV_IRQn; obj_s->error_i2cIRQ = I2C2_ER_IRQn; + +#if defined(TARGET_STM32WL) + /* In Stop2 mode, I2C1 and I2C2 instances are powered down (only I2C3 register content is kept) */ + sleep_manager_lock_deep_sleep(); +#endif } #endif #if defined I2C3_BASE @@ -380,11 +391,17 @@ void i2c_deinit_internal(i2c_t *obj) #if defined I2C1_BASE if (obj_s->i2c == I2C_1) { __HAL_RCC_I2C1_CLK_DISABLE(); +#if defined(TARGET_STM32WL) + sleep_manager_unlock_deep_sleep(); +#endif } #endif #if defined I2C2_BASE if (obj_s->i2c == I2C_2) { __HAL_RCC_I2C2_CLK_DISABLE(); +#if defined(TARGET_STM32WL) + sleep_manager_unlock_deep_sleep(); +#endif } #endif #if defined I2C3_BASE @@ -758,7 +775,7 @@ int i2c_byte_read(i2c_t *obj, int last) if ((tmpreg & I2C_CR2_RELOAD) != 0) { while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) { if ((timeout--) == 0) { - DEBUG_PRINTF("timeout in byte_read\r\n"); + DEBUG_PRINTF("timeout in i2c_byte_read\r\n"); return -1; } } @@ -827,7 +844,7 @@ int i2c_byte_write(i2c_t *obj, int data) if ((tmpreg & I2C_CR2_RELOAD) != 0) { while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) { if ((timeout--) == 0) { - DEBUG_PRINTF("timeout in byte_write\r\n"); + DEBUG_PRINTF("timeout in i2c_byte_write\r\n"); return 2; } } @@ -912,7 +929,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) i2c_ev_err_disable(obj); if ((timeout == 0) || (obj_s->event != I2C_EVENT_TRANSFER_COMPLETE)) { - DEBUG_PRINTF(" TIMEOUT or error in i2c_read\r\n"); + DEBUG_PRINTF("TIMEOUT or error in i2c_read\r\n"); /* re-init IP to try and get back in a working state */ i2c_init_internal(obj, NULL); } else { @@ -986,7 +1003,7 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) count = length; } } else { - DEBUG_PRINTF("ERROR in i2c_read\r\n"); + DEBUG_PRINTF("ERROR in i2c_write\r\n"); } return count;