Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:05

0001 /*
0002  * Copyright (c) 2013 Christian Mauderer.  All rights reserved.
0003  *
0004  * The license and distribution terms for this file may be
0005  * found in the file LICENSE in this distribution or at
0006  * http://www.rtems.org/license/LICENSE.
0007  */
0008 
0009 /* The I2C-module can not run with libi2c. The reason for this is, that libi2c
0010  * needs a possibility to generate a stop condition separately. This controller
0011  * wants to generate the condition automatically when sending or receiving data.
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   /* Make sure, that the module is disabled */
0055   if((regs->cr1 & STM32F4_I2C_CR1_PE) != 0)
0056   {
0057     return RTEMS_RESOURCE_IN_USE;
0058   }
0059 
0060   /* Configure clock control register and rise time register */
0061   ccr = regs->ccr;
0062   trise = regs->trise;
0063 
0064   if(br <= 100000)
0065   {
0066     uint32_t ccr_val = pclk / (2 * br);
0067     /* according to datasheet, the rise time for standard mode is 1us -> 1MHz */
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     /* standard mode */
0077     ccr &= ~STM32F4_I2C_CCR_FS;
0078     ccr = STM32F4_I2C_CCR_CCR_SET(ccr, ccr_val);
0079   }
0080   else
0081   {
0082     /* FIXME: Implement speeds 100kHz < f <= 400kHz (fast mode) */
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   /* This handler implements the suggested read method from stm32f103xx
0095    * reference manual if the handler is not the one with the highest priority */
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     /* Start condition sent. */
0107     regs->dr = e->addr_with_rw;
0108   }
0109 
0110   if(read) {
0111     size_t len = e->len;
0112 
0113     if(len == 1) {
0114       /* special case for one single byte */
0115       if(sr1 & STM32F4_I2C_SR1_ADDR) {
0116         cr1 = regs->cr1;
0117         cr1 &= ~STM32F4_I2C_CR1_ACK;
0118         regs->cr1 = cr1;
0119 
0120         /* Read sr2 to clear flag */
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       /* special case for two bytes */
0132       if(sr1 & STM32F4_I2C_SR1_ADDR) {
0133         /* Read sr2 to clear flag */
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       /* more than two bytes */
0151       if(sr1 & STM32F4_I2C_SR1_ADDR) {
0152         /* Read sr2 to clear flag */
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 /* write */ {
0179     if(sr1 & STM32F4_I2C_SR1_ADDR) {
0180       /* Address sent */
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   /* Create mutex */
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   /* Install interrupt handler and disable this vector */
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   /* Enable module clock */
0243   stm32f4_rcc_set_clock(rcc_index, true);
0244 
0245   /* Setup initial bit rate */
0246   sc = stm32f4_i2c_set_bitrate(e, STM32F4_I2C_INITIAL_BITRATE);
0247   RTEMS_CHECK_SC(sc, "set bitrate");
0248 
0249   /* Set config registers */
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   /* Check if no stop is active. */
0296   if(cr1 & STM32F4_I2C_CR1_STOP) {
0297     return RTEMS_IO_ERROR;
0298   }
0299 
0300   /* Start */
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   /* Wait for end of message */
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