mirror of https://github.com/ARMmbed/mbed-os.git
[STM32_L0] hal improvements
- pins settings - check STM32Cube HAL_Init return valuepull/1072/head
parent
7b6a5eadc6
commit
6433521fc1
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -33,6 +33,7 @@
|
|||
#include "wait_api.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "PeripheralPins.h"
|
||||
|
||||
ADC_HandleTypeDef AdcHandle;
|
||||
|
@ -45,6 +46,11 @@ void analogin_init(analogin_t *obj, PinName pin)
|
|||
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
|
||||
MBED_ASSERT(obj->adc != (ADCName)NC);
|
||||
|
||||
// Get the pin function and assign the used channel to the object
|
||||
uint32_t function = pinmap_function(pin, PinMap_ADC);
|
||||
MBED_ASSERT(function != (uint32_t)NC);
|
||||
obj->channel = STM_PIN_CHANNEL(function);
|
||||
|
||||
// Configure GPIO
|
||||
pinmap_pinout(pin, PinMap_ADC);
|
||||
|
||||
|
@ -77,7 +83,10 @@ void analogin_init(analogin_t *obj, PinName pin)
|
|||
AdcHandle.Init.LowPowerAutoWait = ENABLE;
|
||||
AdcHandle.Init.LowPowerFrequencyMode = DISABLE; // To be enabled only if ADC clock < 2.8 MHz
|
||||
AdcHandle.Init.LowPowerAutoPowerOff = DISABLE;
|
||||
HAL_ADC_Init(&AdcHandle);
|
||||
|
||||
if (HAL_ADC_Init(&AdcHandle) != HAL_OK) {
|
||||
error("Cannot initialize ADC");
|
||||
}
|
||||
|
||||
// Calibration
|
||||
HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED);
|
||||
|
@ -88,58 +97,58 @@ void analogin_init(analogin_t *obj, PinName pin)
|
|||
|
||||
static inline uint16_t adc_read(analogin_t *obj)
|
||||
{
|
||||
ADC_ChannelConfTypeDef sConfig;
|
||||
ADC_ChannelConfTypeDef sConfig = {0};
|
||||
|
||||
AdcHandle.Instance = (ADC_TypeDef *)(obj->adc);
|
||||
|
||||
// Configure ADC channel
|
||||
switch (obj->pin) {
|
||||
case PA_0:
|
||||
switch (obj->channel) {
|
||||
case 0:
|
||||
sConfig.Channel = ADC_CHANNEL_0;
|
||||
break;
|
||||
case PA_1:
|
||||
case 1:
|
||||
sConfig.Channel = ADC_CHANNEL_1;
|
||||
break;
|
||||
case PA_2:
|
||||
case 2:
|
||||
sConfig.Channel = ADC_CHANNEL_2;
|
||||
break;
|
||||
case PA_3:
|
||||
case 3:
|
||||
sConfig.Channel = ADC_CHANNEL_3;
|
||||
break;
|
||||
case PA_4:
|
||||
case 4:
|
||||
sConfig.Channel = ADC_CHANNEL_4;
|
||||
break;
|
||||
case PA_5:
|
||||
case 5:
|
||||
sConfig.Channel = ADC_CHANNEL_5;
|
||||
break;
|
||||
case PA_6:
|
||||
case 6:
|
||||
sConfig.Channel = ADC_CHANNEL_6;
|
||||
break;
|
||||
case PA_7:
|
||||
case 7:
|
||||
sConfig.Channel = ADC_CHANNEL_7;
|
||||
break;
|
||||
case PB_0:
|
||||
case 8:
|
||||
sConfig.Channel = ADC_CHANNEL_8;
|
||||
break;
|
||||
case PB_1:
|
||||
case 9:
|
||||
sConfig.Channel = ADC_CHANNEL_9;
|
||||
break;
|
||||
case PC_0:
|
||||
case 10:
|
||||
sConfig.Channel = ADC_CHANNEL_10;
|
||||
break;
|
||||
case PC_1:
|
||||
case 11:
|
||||
sConfig.Channel = ADC_CHANNEL_11;
|
||||
break;
|
||||
case PC_2:
|
||||
case 12:
|
||||
sConfig.Channel = ADC_CHANNEL_12;
|
||||
break;
|
||||
case PC_3:
|
||||
case 13:
|
||||
sConfig.Channel = ADC_CHANNEL_13;
|
||||
break;
|
||||
case PC_4:
|
||||
case 14:
|
||||
sConfig.Channel = ADC_CHANNEL_14;
|
||||
break;
|
||||
case PC_5:
|
||||
case 15:
|
||||
sConfig.Channel = ADC_CHANNEL_15;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -40,8 +40,8 @@
|
|||
static DAC_HandleTypeDef DacHandle;
|
||||
|
||||
// These variables are used for the "free" function
|
||||
static int pa4_used = 0;
|
||||
static int pa5_used = 0;
|
||||
static int channel1_used = 0;
|
||||
static int channel2_used = 0;
|
||||
|
||||
void analogout_init(dac_t *obj, PinName pin)
|
||||
{
|
||||
|
@ -51,6 +51,11 @@ void analogout_init(dac_t *obj, PinName pin)
|
|||
obj->dac = (DACName)pinmap_peripheral(pin, PinMap_DAC);
|
||||
MBED_ASSERT(obj->dac != (DACName)NC);
|
||||
|
||||
// Get the pin function and assign the used channel to the object
|
||||
uint32_t function = pinmap_function(pin, PinMap_DAC);
|
||||
MBED_ASSERT(function != (uint32_t)NC);
|
||||
obj->channel = STM_PIN_CHANNEL(function);
|
||||
|
||||
// Configure GPIO
|
||||
pinmap_pinout(pin, PinMap_DAC);
|
||||
|
||||
|
@ -66,17 +71,22 @@ void analogout_init(dac_t *obj, PinName pin)
|
|||
sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
|
||||
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
|
||||
|
||||
if (pin == PA_4) {
|
||||
HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_1);
|
||||
pa4_used = 1;
|
||||
}
|
||||
|
||||
#if defined(DAC_CHANNEL_2)
|
||||
if (pin == PA_5) {
|
||||
HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_2);
|
||||
pa5_used = 1;
|
||||
}
|
||||
if (obj->channel == 2) {
|
||||
if (HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_2) != HAL_OK) {
|
||||
error("Cannot configure DAC channel 2");
|
||||
}
|
||||
channel2_used = 1;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// channel 1 per default
|
||||
if (HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_1) != HAL_OK) {
|
||||
error("Cannot configure DAC channel 1");
|
||||
}
|
||||
obj->channel = 1;
|
||||
channel1_used = 1;
|
||||
}
|
||||
|
||||
analogout_write_u16(obj, 0);
|
||||
}
|
||||
|
@ -84,10 +94,10 @@ void analogout_init(dac_t *obj, PinName pin)
|
|||
void analogout_free(dac_t *obj)
|
||||
{
|
||||
// Reset DAC and disable clock
|
||||
if (obj->pin == PA_4) pa4_used = 0;
|
||||
if (obj->pin == PA_5) pa5_used = 0;
|
||||
if (obj->channel == 1) channel1_used = 0;
|
||||
if (obj->channel == 2) channel2_used = 0;
|
||||
|
||||
if ((pa4_used == 0) && (pa5_used == 0)) {
|
||||
if ((channel1_used == 0) && (channel2_used == 0)) {
|
||||
__DAC_FORCE_RESET();
|
||||
__DAC_RELEASE_RESET();
|
||||
__DAC_CLK_DISABLE();
|
||||
|
@ -99,13 +109,12 @@ void analogout_free(dac_t *obj)
|
|||
|
||||
static inline void dac_write(dac_t *obj, uint16_t value)
|
||||
{
|
||||
if (obj->pin == PA_4) {
|
||||
if (obj->channel == 1) {
|
||||
HAL_DAC_SetValue(&DacHandle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, value);
|
||||
HAL_DAC_Start(&DacHandle, DAC_CHANNEL_1);
|
||||
}
|
||||
|
||||
#if defined(DAC_CHANNEL_2)
|
||||
if (obj->pin == PA_5) {
|
||||
if (obj->channel == 2) {
|
||||
HAL_DAC_SetValue(&DacHandle, DAC_CHANNEL_2, DAC_ALIGN_12B_R, value);
|
||||
HAL_DAC_Start(&DacHandle, DAC_CHANNEL_2);
|
||||
}
|
||||
|
@ -114,17 +123,15 @@ static inline void dac_write(dac_t *obj, uint16_t value)
|
|||
|
||||
static inline int dac_read(dac_t *obj)
|
||||
{
|
||||
if (obj->pin == PA_4) {
|
||||
if (obj->channel == 1) {
|
||||
return (int)HAL_DAC_GetValue(&DacHandle, DAC_CHANNEL_1);
|
||||
}
|
||||
#if defined(DAC_CHANNEL_2)
|
||||
else if (obj->pin == PA_5) {
|
||||
if (obj->channel == 2) {
|
||||
return (int)HAL_DAC_GetValue(&DacHandle, DAC_CHANNEL_2);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void analogout_write(dac_t *obj, float value)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -76,8 +76,8 @@ static uint32_t pin_base_nr[16] = {
|
|||
7, // pin 11
|
||||
8, // pin 12
|
||||
9, // pin 13
|
||||
10, // pin 14
|
||||
11 // pin 15
|
||||
10, // pin 14
|
||||
11 // pin 15
|
||||
};
|
||||
|
||||
static gpio_irq_handler irq_handler;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -64,7 +64,8 @@ static inline int gpio_read(gpio_t *obj)
|
|||
return ((*obj->reg_in & obj->mask) ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline int gpio_is_connected(const gpio_t *obj) {
|
||||
static inline int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return obj->pin != (PinName)NC;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "PeripheralPins.h"
|
||||
|
||||
/* Timeout values for flags and events waiting loops. These timeouts are
|
||||
|
@ -135,7 +136,10 @@ void i2c_frequency(i2c_t *obj, int hz)
|
|||
I2cHandle.Init.OwnAddress1 = 0;
|
||||
I2cHandle.Init.OwnAddress2 = 0;
|
||||
I2cHandle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
|
||||
HAL_I2C_Init(&I2cHandle);
|
||||
|
||||
if (HAL_I2C_Init(&I2cHandle) != HAL_OK) {
|
||||
error("Cannot initialize I2C");
|
||||
}
|
||||
}
|
||||
|
||||
inline int i2c_start(i2c_t *obj)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -33,6 +33,7 @@
|
|||
#include "mbed_error.h"
|
||||
|
||||
// GPIO mode look-up table
|
||||
// Warning: order must be the same as the one defined in PinNames.h !!!
|
||||
static const uint32_t gpio_mode[13] = {
|
||||
0x00000000, // 0 = GPIO_MODE_INPUT
|
||||
0x00000001, // 1 = GPIO_MODE_OUTPUT_PP
|
||||
|
@ -62,18 +63,24 @@ uint32_t Set_GPIO_Clock(uint32_t port_idx)
|
|||
gpio_add = GPIOB_BASE;
|
||||
__GPIOB_CLK_ENABLE();
|
||||
break;
|
||||
#if defined(GPIOC_BASE)
|
||||
case PortC:
|
||||
gpio_add = GPIOC_BASE;
|
||||
__GPIOC_CLK_ENABLE();
|
||||
break;
|
||||
#endif
|
||||
#if defined(GPIOD_BASE)
|
||||
case PortD:
|
||||
gpio_add = GPIOD_BASE;
|
||||
__GPIOD_CLK_ENABLE();
|
||||
break;
|
||||
#endif
|
||||
#if defined(GPIOH_BASE)
|
||||
case PortH:
|
||||
gpio_add = GPIOH_BASE;
|
||||
__GPIOH_CLK_ENABLE();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error("Pinmap error: wrong port number.");
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -42,10 +42,13 @@ void pwmout_init(pwmout_t* obj, PinName pin)
|
|||
{
|
||||
// Get the peripheral name from the pin and assign it to the object
|
||||
obj->pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
|
||||
MBED_ASSERT(obj->pwm != (PWMName)NC);
|
||||
|
||||
if (obj->pwm == (PWMName)NC) {
|
||||
error("PWM error: pinout mapping failed.");
|
||||
}
|
||||
// Get the pin function and assign the used channel to the object
|
||||
uint32_t function = pinmap_function(pin, PinMap_PWM);
|
||||
MBED_ASSERT(function != (uint32_t)NC);
|
||||
obj->channel = STM_PIN_CHANNEL(function);
|
||||
obj->inverted = STM_PIN_INVERTED(function);
|
||||
|
||||
// Enable TIM clock
|
||||
if (obj->pwm == PWM_2) __TIM2_CLK_ENABLE();
|
||||
|
@ -92,43 +95,27 @@ void pwmout_write(pwmout_t* obj, float value)
|
|||
sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
sConfig.OCFastMode = TIM_OCFAST_ENABLE;
|
||||
|
||||
switch (obj->pin) {
|
||||
// Channels 1
|
||||
case PA_0:
|
||||
case PA_5:
|
||||
case PA_6:
|
||||
case PA_15:
|
||||
case PB_4:
|
||||
case PC_6:
|
||||
switch (obj->channel) {
|
||||
case 1:
|
||||
channel = TIM_CHANNEL_1;
|
||||
break;
|
||||
// Channels 2
|
||||
case PA_1:
|
||||
case PA_7:
|
||||
case PB_3:
|
||||
case PB_5:
|
||||
case PC_7:
|
||||
case 2:
|
||||
channel = TIM_CHANNEL_2;
|
||||
break;
|
||||
// Channels 3
|
||||
case PA_2:
|
||||
case PB_0:
|
||||
case PB_10:
|
||||
case PC_8:
|
||||
case 3:
|
||||
channel = TIM_CHANNEL_3;
|
||||
break;
|
||||
// Channels 4
|
||||
case PA_3:
|
||||
case PB_1:
|
||||
case PB_11:
|
||||
case PC_9:
|
||||
case 4:
|
||||
channel = TIM_CHANNEL_4;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, channel);
|
||||
if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, channel) != HAL_OK) {
|
||||
error("Cannot initialize PWM");
|
||||
}
|
||||
|
||||
HAL_TIM_PWM_Start(&TimHandle, channel);
|
||||
}
|
||||
|
||||
|
@ -163,7 +150,10 @@ void pwmout_period_us(pwmout_t* obj, int us)
|
|||
TimHandle.Init.Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
|
||||
TimHandle.Init.ClockDivision = 0;
|
||||
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
HAL_TIM_PWM_Init(&TimHandle);
|
||||
|
||||
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
|
||||
error("Cannot initialize PWM");
|
||||
}
|
||||
|
||||
// Set duty cycle again
|
||||
pwmout_write(obj, dc);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include <string.h>
|
||||
#include "PeripheralPins.h"
|
||||
|
||||
|
@ -74,7 +75,9 @@ static void init_uart(serial_t *obj)
|
|||
UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT;
|
||||
UartHandle.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
|
||||
|
||||
HAL_UART_Init(&UartHandle);
|
||||
if (HAL_UART_Init(&UartHandle) != HAL_OK) {
|
||||
error("Cannot initialize UART");
|
||||
}
|
||||
}
|
||||
|
||||
void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -35,6 +35,7 @@
|
|||
#include <math.h>
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "PeripheralPins.h"
|
||||
|
||||
static SPI_HandleTypeDef SpiHandle;
|
||||
|
@ -57,7 +58,9 @@ static void init_spi(spi_t *obj)
|
|||
SpiHandle.Init.NSS = obj->nss;
|
||||
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED;
|
||||
|
||||
HAL_SPI_Init(&SpiHandle);
|
||||
if (HAL_SPI_Init(&SpiHandle) != HAL_OK) {
|
||||
error("Cannot initialize SPI");
|
||||
}
|
||||
|
||||
__HAL_SPI_ENABLE(&SpiHandle);
|
||||
}
|
||||
|
@ -193,6 +196,7 @@ void spi_frequency(spi_t *obj, int hz)
|
|||
} else { // >= 16000000
|
||||
obj->br_presc = SPI_BAUDRATEPRESCALER_2; // 16 MHz
|
||||
}
|
||||
|
||||
init_spi(obj);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2014, STMicroelectronics
|
||||
* Copyright (c) 2015, STMicroelectronics
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
Loading…
Reference in New Issue