Statistics
| Branch: | Tag: | Revision:

amiro-os / boards / PowerManagement / board.c @ f0393a37

History | View | Annotate | Download (6.464 KB)

1
#include "ch.h"
2
#include "hal.h"
3
#include "board.h"
4

    
5
/**
6
 * @brief   PAL setup.
7
 * @details Digital I/O ports static configuration as defined in @p board.h.
8
 *          This variable is used by the HAL when initializing the PAL driver.
9
 */
10
#if HAL_USE_PAL || defined(__DOXYGEN__)
11
const PALConfig pal_default_config =
12
{
13
  {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
14
  {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
15
  {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
16
  {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
17
  {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
18
  {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
19
  {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
20
  {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
21
  {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}
22
};
23
#endif
24

    
25
/*
26
 * Early initialization code.
27
 * This initialization must be performed just after stack setup and before
28
 * any other initialization.
29
 */
30
void __early_init(void) {
31

    
32
  stm32_clock_init();
33
}
34

    
35
/*
36
 * Board-specific initialization code.
37
 */
38
void boardInit(void) {
39

    
40
}
41

    
42
inline void boardWriteIoPower(int value)
43
{
44
    palWritePad(GPIOA, GPIOA_SYS_REG_EN, value);
45
    if (value) {
46
        // drive pins
47
        palSetPadMode(GPIOA, GPIOA_CAN_TX, PAL_MODE_ALTERNATE(9));
48
        palSetPadMode(GPIOA, GPIOA_SYS_UART_TX, PAL_MODE_ALTERNATE(7));
49
        palSetPadMode(GPIOB, GPIOB_BT_CTS, PAL_MODE_ALTERNATE(7));
50
    } else {
51
        // float pins
52
        palSetPadMode(GPIOA, GPIOA_CAN_TX, PAL_MODE_INPUT);
53
        palSetPadMode(GPIOA, GPIOA_SYS_UART_TX, PAL_MODE_INPUT);
54
        palSetPadMode(GPIOB, GPIOB_BT_CTS, PAL_MODE_INPUT);
55
    }
56
    chThdSleepMilliseconds(50);
57
}
58

    
59
inline void boardWriteLed(int value)
60
{
61
    palWritePad(GPIOB, GPIOB_LED, !value);
62
}
63

    
64
inline void boardWriteSystemPower(int value)
65
{
66
    palWritePad(GPIOB, GPIOB_POWER_EN, value);
67
    chThdSleepMilliseconds(50);
68
}
69

    
70
inline void boardWriteWarmRestart(const uint8_t value)
71
{
72
    palWritePad(GPIOC, GPIOC_SYS_WARMRST_N, ~value);
73
    chThdSleepMilliseconds(50);
74
}
75

    
76
inline void boardChargerSetState(uint8_t chrg_mask, uint8_t state)
77
{
78
  if (chrg_mask & (1u << 0))
79
    palWritePad(GPIOC, GPIOC_CHARGE_EN1_N, ~state);
80
  if (chrg_mask & (1u << 1))
81
    palWritePad(GPIOD, GPIOD_CHARGE_EN2_N, ~state);
82
}
83

    
84
inline void boardBluetoothSetState(uint8_t state)
85
{
86
    palWritePad(GPIOC, GPIOC_BT_RST, ~state);
87
}
88

    
89
inline void boardRequestShutdown(void)
90
{
91
  palClearPad(GPIOC, GPIOC_SYS_PD_N);
92
}
93

    
94
#define RTC_ISR_TAMP2F ((uint32_t)0x00004000)
95

    
96
inline void boardStandby(void)
97
{
98

    
99
  chSysLock();
100
  // set deepsleep bit
101
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
102
  // enable wakeup pin
103
  PWR->CSR |= PWR_CSR_EWUP;
104
  // set PDDS, clear WUF, clear SBF
105
  PWR->CR |= (PWR_CR_CWUF | PWR_CR_PDDS | PWR_CR_CSBF);
106
  // clear RTC wakeup source flags
107
  RTC->ISR &= ~(RTC_ISR_ALRBF | RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TAMP1F | RTC_ISR_TAMP2F |
108
                RTC_ISR_TSOVF | RTC_ISR_TSF);
109
  // Wait for Interrupt
110
  __WFI();
111

    
112
}
113

    
114
inline void boardStop(const uint8_t lpds, const uint8_t fpds)
115
{
116

    
117
  chSysLock();
118
  // set deepsleep bit
119
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
120
  // enable wakeup pin
121
  //PWR->CSR |= PWR_CSR_EWUP;
122
  // clear PDDS, clear LPDS, clear FPDS
123
  PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_FPDS);
124
  // clear WUF, clear SBF
125
  PWR->CR |= (PWR_CR_CWUF | PWR_CR_CSBF);
126
  if (lpds)
127
    PWR->CR |= (PWR_CR_LPDS);
128
  if (fpds)
129
    PWR->CR |= (PWR_CR_FPDS);
130
  // clear RTC wakeup source flags
131
  RTC->ISR &= ~(RTC_ISR_ALRBF | RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TAMP1F | RTC_ISR_TAMP2F |
132
                RTC_ISR_TSOVF | RTC_ISR_TSF);
133
  // clear pending interrupts
134
  EXTI->PR = ~0;
135
  // Wait for Interrupt
136
  __WFI();
137

    
138
}
139

    
140
#undef RTC_ISR_TAMP2F
141

    
142
inline void boardWakeup(void) {
143

    
144
  palClearPad(GPIOC, GPIOC_SYS_PD_N);
145
  chThdSleepMicroseconds(10);
146
  palSetPad(GPIOC, GPIOC_SYS_PD_N);
147
}
148

    
149
inline void boardClearI2CBus(const uint8_t scl_pad, const uint8_t sda_pad) {
150

    
151
  uint8_t i;
152

    
153
  // configure I²C SCL and SDA open drain
154
  palSetPadMode(GPIOB, scl_pad, PAL_MODE_OUTPUT_OPENDRAIN);
155
  palSetPadMode(GPIOB, sda_pad, PAL_MODE_OUTPUT_OPENDRAIN);
156

    
157
  // perform a 2-wire software reset for the eeprom (see AT24C01BN-SH-B datasheet, chapter 3)
158
  // note: clock is ~50kHz (20us per cycle)
159
  palSetPad(GPIOB, sda_pad);
160
  palClearPad(GPIOB, scl_pad);
161
  chThdSleepMicroseconds(10);
162
  palSetPad(GPIOB, scl_pad);
163
  chThdSleepMicroseconds(5);
164
  palClearPad(GPIOB, sda_pad);
165
  chThdSleepMicroseconds(5);
166
  palClearPad(GPIOB, scl_pad);
167
  chThdSleepMicroseconds(5);
168
  palSetPad(GPIOB, sda_pad);
169
  chThdSleepMicroseconds(5);
170
  for (i = 0; i < 9; ++i) {
171
    palSetPad(GPIOB, scl_pad);
172
    chThdSleepMicroseconds(10);
173
    palClearPad(GPIOB, scl_pad);
174
    chThdSleepMicroseconds(10);
175
  }
176
  palSetPad(GPIOB, scl_pad);
177
  chThdSleepMicroseconds(5);
178
  palClearPad(GPIOB, sda_pad);
179
  chThdSleepMicroseconds(5);
180
  palClearPad(GPIOB, scl_pad);
181
  chThdSleepMicroseconds(10);
182
  palSetPad(GPIOB, scl_pad);
183
  chThdSleepMicroseconds(5);
184
  palSetPad(GPIOB, sda_pad);
185
  chThdSleepMicroseconds(5);
186
  palClearPad(GPIOB, scl_pad);
187
  chThdSleepMicroseconds(10);
188

    
189
  // perform bus clear as per I²C Specification v6 3.1.16
190
  // note: clock is 100kHz (10us per cycle)
191
  for (i = 0; i < 10; i++) {
192
    palClearPad(GPIOB, scl_pad);
193
    chThdSleepMicroseconds(5);
194
    palSetPad(GPIOB, scl_pad);
195
    chThdSleepMicroseconds(5);
196
  }
197

    
198
  // reconfigure I²C SCL
199
  palSetPadMode(GPIOB, scl_pad, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN);
200
  palSetPadMode(GPIOB, sda_pad, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN);
201

    
202
  return;
203
}
204

    
205
inline void boardResetBQ27500I2C(const uint8_t scl_pad, const uint8_t sda_pad) {
206

    
207
  // configure I²C SCL and SDA open drain
208
  palSetPadMode(GPIOB, scl_pad, PAL_MODE_OUTPUT_OPENDRAIN);
209
  palSetPadMode(GPIOB, sda_pad, PAL_MODE_OUTPUT_OPENDRAIN);
210

    
211
  // BQ27500: reset by holding bus low for t_BUSERR (17.3 - 21.2 seconds)
212
  palClearPad(GPIOB, scl_pad);
213
  palClearPad(GPIOB, sda_pad);
214
  chThdSleepSeconds(20);
215

    
216
  boardClearI2CBus(scl_pad, sda_pad);
217

    
218
  return;
219
}