File indexing completed on 2025-05-11 08:23:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <bsp.h>
0015 #include <bsp/i2c.h>
0016 #include <bsp/rcc.h>
0017 #include <bsp/irq.h>
0018 #include <bsp/irq-generic.h>
0019 #include <assert.h>
0020
0021 #define RTEMS_STATUS_CHECKS_USE_PRINTK
0022
0023 #include <rtems/status-checks.h>
0024
0025 #define STM32F4_I2C_INITIAL_BITRATE 100000
0026
0027 #define I2C_RW_BIT 0x1
0028
0029 stm32f4_rcc_index i2c_rcc_index [] = {
0030 STM32F4_RCC_I2C1,
0031 STM32F4_RCC_I2C2,
0032 };
0033
0034 static stm32f4_rcc_index i2c_get_rcc_index(stm32f4_i2c_bus_entry *e)
0035 {
0036 return i2c_rcc_index [e->index];
0037 }
0038
0039 static uint32_t i2c_get_pclk(stm32f4_i2c_bus_entry *e)
0040 {
0041 return STM32F4_PCLK1;
0042 }
0043
0044 rtems_status_code stm32f4_i2c_set_bitrate(
0045 stm32f4_i2c_bus_entry *e,
0046 uint32_t br
0047 )
0048 {
0049 volatile stm32f4_i2c *regs = e->regs;
0050 uint32_t ccr;
0051 uint32_t trise;
0052 uint32_t pclk = i2c_get_pclk(e);
0053
0054
0055 if((regs->cr1 & STM32F4_I2C_CR1_PE) != 0)
0056 {
0057 return RTEMS_RESOURCE_IN_USE;
0058 }
0059
0060
0061 ccr = regs->ccr;
0062 trise = regs->trise;
0063
0064 if(br <= 100000)
0065 {
0066 uint32_t ccr_val = pclk / (2 * br);
0067
0068 uint32_t trise_val = pclk / 1000000 + 1;
0069 trise = STM32F4_I2C_TRISE_SET(trise, trise_val);
0070
0071 if(ccr_val > STM32F4_I2C_CCR_CCR_MAX)
0072 {
0073 return RTEMS_INVALID_NUMBER;
0074 }
0075
0076
0077 ccr &= ~STM32F4_I2C_CCR_FS;
0078 ccr = STM32F4_I2C_CCR_CCR_SET(ccr, ccr_val);
0079 }
0080 else
0081 {
0082
0083 return RTEMS_NOT_IMPLEMENTED;
0084 }
0085
0086 regs->ccr = ccr;
0087 regs->trise = trise;
0088
0089 return RTEMS_SUCCESSFUL;
0090 }
0091
0092 static void stm32f4_i2c_handler(void *arg)
0093 {
0094
0095
0096 stm32f4_i2c_bus_entry *e = arg;
0097 volatile stm32f4_i2c *regs = e->regs;
0098 uint32_t sr1 = regs->sr1;
0099 uint8_t *data = e->data;
0100 uint8_t *last = e->last;
0101 bool read = e->read;
0102 bool wake_task = false;
0103 uint32_t cr1;
0104
0105 if(sr1 & STM32F4_I2C_SR1_SB) {
0106
0107 regs->dr = e->addr_with_rw;
0108 }
0109
0110 if(read) {
0111 size_t len = e->len;
0112
0113 if(len == 1) {
0114
0115 if(sr1 & STM32F4_I2C_SR1_ADDR) {
0116 cr1 = regs->cr1;
0117 cr1 &= ~STM32F4_I2C_CR1_ACK;
0118 regs->cr1 = cr1;
0119
0120
0121 regs->sr2;
0122
0123 cr1 = regs->cr1;
0124 cr1 |= STM32F4_I2C_CR1_STOP;
0125 regs->cr1 = cr1;
0126 } else if(sr1 & STM32F4_I2C_SR1_RxNE) {
0127 *data = regs->dr;
0128 wake_task = true;
0129 }
0130 } else if (len == 2) {
0131
0132 if(sr1 & STM32F4_I2C_SR1_ADDR) {
0133
0134 regs->sr2;
0135
0136 cr1 = regs->cr1;
0137 cr1 &= ~STM32F4_I2C_CR1_ACK;
0138 regs->cr1 = cr1;
0139 } else if(sr1 & STM32F4_I2C_SR1_BTF) {
0140 cr1 = regs->cr1;
0141 cr1 |= STM32F4_I2C_CR1_STOP;
0142 regs->cr1 = cr1;
0143
0144 *data = regs->dr;
0145 ++data;
0146 *data = regs->dr;
0147 wake_task = true;
0148 }
0149 } else {
0150
0151 if(sr1 & STM32F4_I2C_SR1_ADDR) {
0152
0153 regs->sr2;
0154 } else if(sr1 & STM32F4_I2C_SR1_BTF && data == last - 2) {
0155 cr1 = regs->cr1;
0156 cr1 &= ~STM32F4_I2C_CR1_ACK;
0157 regs->cr1 = cr1;
0158
0159 *data = regs->dr;
0160 ++data;
0161
0162 cr1 = regs->cr1;
0163 cr1 |= STM32F4_I2C_CR1_STOP;
0164 regs->cr1 = cr1;
0165
0166 *data = regs->dr;
0167 ++data;
0168 } else if((sr1 & STM32F4_I2C_SR1_RxNE) && (data != last - 2)) {
0169 *data = regs->dr;
0170
0171 if(data == last) {
0172 wake_task = true;
0173 } else {
0174 ++data;
0175 }
0176 }
0177 }
0178 } else {
0179 if(sr1 & STM32F4_I2C_SR1_ADDR) {
0180
0181 regs->sr2;
0182 }
0183
0184 if((sr1 & (STM32F4_I2C_SR1_ADDR | STM32F4_I2C_SR1_TxE)) && (data <= last)) {
0185 regs->dr = *data;
0186 ++data;
0187 } else if(sr1 & STM32F4_I2C_SR1_BTF) {
0188 uint32_t cr1 = regs->cr1;
0189 cr1 |= STM32F4_I2C_CR1_STOP;
0190 regs->cr1 = cr1;
0191 wake_task = true;
0192 }
0193 }
0194
0195 e->data = data;
0196
0197 if(wake_task) {
0198 bsp_interrupt_vector_disable(e->vector);
0199 rtems_event_transient_send(e->task_id);
0200 }
0201 }
0202
0203 static rtems_status_code i2c_wait_done(stm32f4_i2c_bus_entry *e)
0204 {
0205 bsp_interrupt_vector_enable(e->vector);
0206 e->task_id = rtems_task_self();
0207 return rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0208 }
0209
0210 rtems_status_code stm32f4_i2c_init(stm32f4_i2c_bus_entry *e)
0211 {
0212 rtems_status_code sc = RTEMS_SUCCESSFUL;
0213 volatile stm32f4_i2c *regs = e->regs;
0214 stm32f4_rcc_index rcc_index = i2c_get_rcc_index(e);
0215 uint32_t pclk = i2c_get_pclk(e);
0216 uint32_t cr1 = 0;
0217 uint32_t cr2 = 0;
0218
0219 assert(pclk >= 2000000);
0220
0221
0222 sc = rtems_semaphore_create (
0223 rtems_build_name ('I', '2', 'C', '1' + e->index),
0224 0,
0225 RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
0226 0,
0227 &e->mutex
0228 );
0229 RTEMS_CHECK_SC(sc, "create mutex");
0230
0231
0232 sc = rtems_interrupt_handler_install(
0233 e->vector,
0234 "I2C",
0235 RTEMS_INTERRUPT_UNIQUE,
0236 stm32f4_i2c_handler,
0237 e
0238 );
0239 RTEMS_CHECK_SC(sc, "install interrupt handler");
0240 bsp_interrupt_vector_disable(e->vector);
0241
0242
0243 stm32f4_rcc_set_clock(rcc_index, true);
0244
0245
0246 sc = stm32f4_i2c_set_bitrate(e, STM32F4_I2C_INITIAL_BITRATE);
0247 RTEMS_CHECK_SC(sc, "set bitrate");
0248
0249
0250 cr2 = regs->cr2;
0251 cr2 = STM32F4_I2C_CR2_FREQ_SET(cr2, pclk / 1000000);
0252 cr2 |= STM32F4_I2C_CR2_ITEVTEN;
0253 cr2 |= STM32F4_I2C_CR2_ITBUFEN;
0254 regs->cr2 = cr2;
0255
0256 cr1 = regs->cr1;
0257 cr1 |= STM32F4_I2C_CR1_PE;
0258 regs->cr1 = cr1;
0259
0260 return RTEMS_SUCCESSFUL;
0261 }
0262
0263 rtems_status_code stm32f4_i2c_process_message(
0264 stm32f4_i2c_bus_entry *e,
0265 stm32f4_i2c_message *msg
0266 )
0267 {
0268 rtems_status_code sc = RTEMS_SUCCESSFUL;
0269 rtems_status_code sc_return = RTEMS_SUCCESSFUL;
0270 volatile stm32f4_i2c *regs = e->regs;
0271 uint16_t max_7_bit_address = (1 << 7) - 1;
0272 uint32_t cr1 = regs->cr1;
0273
0274 if(msg->addr > max_7_bit_address) {
0275 return RTEMS_NOT_IMPLEMENTED;
0276 }
0277
0278 if(msg->len == 0) {
0279 return RTEMS_INVALID_SIZE;
0280 }
0281
0282 sc = rtems_semaphore_obtain(e->mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0283 RTEMS_CHECK_SC(sc, "obtaining mutex");
0284
0285 e->data = msg->buf;
0286 e->last = msg->buf + msg->len - 1;
0287 e->len = msg->len;
0288
0289 e->addr_with_rw = msg->addr << 1;
0290 if(msg->read) {
0291 e->addr_with_rw |= I2C_RW_BIT;
0292 }
0293 e->read = msg->read;
0294
0295
0296 if(cr1 & STM32F4_I2C_CR1_STOP) {
0297 return RTEMS_IO_ERROR;
0298 }
0299
0300
0301 cr1 = regs->cr1;
0302 if(e->len == 2) {
0303 cr1 |= STM32F4_I2C_CR1_POS;
0304 } else {
0305 cr1 &= ~STM32F4_I2C_CR1_POS;
0306 }
0307 cr1 |= STM32F4_I2C_CR1_ACK;
0308 cr1 |= STM32F4_I2C_CR1_START;
0309 regs->cr1 = cr1;
0310
0311
0312 sc = i2c_wait_done(e);
0313
0314 if(sc != RTEMS_SUCCESSFUL) {
0315 sc_return = sc;
0316 }
0317
0318 sc = rtems_semaphore_release(e->mutex);
0319 RTEMS_CHECK_SC(sc, "releasing mutex");
0320
0321 return sc_return;
0322 }
0323