@@ -341,6 +341,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
341
341
// I2C Xfer operation init
342
342
obj_s -> event = 0 ;
343
343
obj_s -> XferOperation = I2C_FIRST_AND_LAST_FRAME ;
344
+ #ifdef I2C_IP_VERSION_V2
345
+ obj_s -> pending_start = 0 ;
346
+ #endif
344
347
}
345
348
346
349
void i2c_frequency (i2c_t * obj , int hz )
@@ -440,6 +443,14 @@ i2c_t *get_i2c_obj(I2C_HandleTypeDef *hi2c){
440
443
return (obj );
441
444
}
442
445
446
+ void i2c_reset (i2c_t * obj ) {
447
+ struct i2c_s * obj_s = I2C_S (obj );
448
+ /* As recommended in i2c_api.h, mainly send stop */
449
+ i2c_stop (obj );
450
+ /* then re-init */
451
+ i2c_init (obj , obj_s -> sda , obj_s -> scl );
452
+ }
453
+
443
454
/*
444
455
* UNITARY APIS.
445
456
* For very basic operations, direct registers access is needed
@@ -535,7 +546,7 @@ int i2c_byte_write(i2c_t *obj, int data) {
535
546
(__HAL_I2C_GET_FLAG (handle , I2C_FLAG_BTF ) == RESET ) &&
536
547
(__HAL_I2C_GET_FLAG (handle , I2C_FLAG_ADDR ) == RESET )) {
537
548
if ((timeout -- ) == 0 ) {
538
- return 0 ;
549
+ return 2 ;
539
550
}
540
551
}
541
552
@@ -548,92 +559,161 @@ int i2c_byte_write(i2c_t *obj, int data) {
548
559
}
549
560
#endif //I2C_IP_VERSION_V1
550
561
#ifdef I2C_IP_VERSION_V2
562
+
551
563
int i2c_start (i2c_t * obj ) {
552
564
struct i2c_s * obj_s = I2C_S (obj );
553
- I2C_HandleTypeDef * handle = & (obj_s -> handle );
554
- I2C_TypeDef * i2c = (I2C_TypeDef * )obj_s -> i2c ;
555
- int timeout ;
556
-
557
- // Clear Acknowledge failure flag
558
- __HAL_I2C_CLEAR_FLAG (handle , I2C_FLAG_AF );
565
+ /* This I2C IP doesn't */
566
+ obj_s -> pending_start = 1 ;
567
+ return 0 ;
568
+ }
559
569
560
- // Wait the STOP condition has been previously correctly sent
561
- timeout = FLAG_TIMEOUT ;
562
- while ((i2c -> CR2 & I2C_CR2_STOP ) == I2C_CR2_STOP ){
563
- if ((timeout -- ) == 0 ) {
564
- return 1 ;
565
- }
570
+ int i2c_stop (i2c_t * obj ) {
571
+ struct i2c_s * obj_s = I2C_S (obj );
572
+ I2C_HandleTypeDef * handle = & (obj_s -> handle );
573
+ int timeout = FLAG_TIMEOUT ;
574
+ #if DEVICE_I2CSLAVE
575
+ if (obj_s -> slave ) {
576
+ /* re-init slave when stop is requested */
577
+ i2c_init (obj , obj_s -> sda , obj_s -> scl );
578
+ return 0 ;
566
579
}
580
+ #endif
581
+ // Disable reload mode
582
+ handle -> Instance -> CR2 &= (uint32_t )~I2C_CR2_RELOAD ;
583
+ // Generate the STOP condition
584
+ handle -> Instance -> CR2 |= I2C_CR2_STOP ;
567
585
568
- // Generate the START condition
569
- i2c -> CR2 |= I2C_CR2_START ;
570
-
571
- // Wait the START condition has been correctly sent
572
586
timeout = FLAG_TIMEOUT ;
573
- while (__HAL_I2C_GET_FLAG (handle , I2C_FLAG_BUSY ) == RESET ) {
587
+ while (! __HAL_I2C_GET_FLAG (handle , I2C_FLAG_STOPF ) ) {
574
588
if ((timeout -- ) == 0 ) {
575
- return 1 ;
589
+ return I2C_ERROR_BUS_BUSY ;
576
590
}
577
591
}
578
592
579
- return 0 ;
580
- }
593
+ /* Clear STOP Flag */
594
+ __HAL_I2C_CLEAR_FLAG ( handle , I2C_FLAG_STOPF );
581
595
582
- int i2c_stop ( i2c_t * obj ) {
583
- struct i2c_s * obj_s = I2C_S ( obj );
584
- I2C_TypeDef * i2c = ( I2C_TypeDef * ) obj_s -> i2c ;
596
+ /* Erase slave address, this wiil be used as a marker
597
+ * to know when we need to prepare next start */
598
+ handle -> Instance -> CR2 &= ~ I2C_CR2_SADD ;
585
599
586
- // Generate the STOP condition
587
- i2c -> CR2 |= I2C_CR2_STOP ;
600
+ /* In case of mixed usage of the APIs (unitary + SYNC)
601
+ * re-inti HAL state */
602
+ if (obj_s -> XferOperation != I2C_FIRST_AND_LAST_FRAME ) {
603
+ i2c_init (obj , obj_s -> sda , obj_s -> scl );
604
+ }
588
605
589
606
return 0 ;
590
607
}
591
608
592
609
int i2c_byte_read (i2c_t * obj , int last ) {
593
610
struct i2c_s * obj_s = I2C_S (obj );
594
- I2C_TypeDef * i2c = (I2C_TypeDef * )obj_s -> i2c ;
595
611
I2C_HandleTypeDef * handle = & (obj_s -> handle );
596
- int timeout ;
612
+ int timeout = FLAG_TIMEOUT ;
613
+ uint32_t tmpreg = handle -> Instance -> CR2 ;
614
+ char data ;
615
+ #if DEVICE_I2CSLAVE
616
+ if (obj_s -> slave ) {
617
+ return i2c_slave_read (obj , & data , 1 );
618
+ }
619
+ #endif
620
+ /* Then send data when there's room in the TX fifo */
621
+ if ((tmpreg & I2C_CR2_RELOAD ) != 0 ) {
622
+ while (!__HAL_I2C_GET_FLAG (handle , I2C_FLAG_TCR )) {
623
+ if ((timeout -- ) == 0 ) {
624
+ DEBUG_PRINTF ("timeout in byte_read\r\n" );
625
+ return -1 ;
626
+ }
627
+ }
628
+ }
629
+
630
+ /* Enable reload mode as we don't know how many bytes will eb sent */
631
+ handle -> Instance -> CR2 |= I2C_CR2_RELOAD ;
632
+ /* Set transfer size to 1 */
633
+ handle -> Instance -> CR2 |= (I2C_CR2_NBYTES & (1 << 16 ));
634
+ /* Set the prepared configuration */
635
+ handle -> Instance -> CR2 = tmpreg ;
597
636
598
- // Wait until the byte is received
599
637
timeout = FLAG_TIMEOUT ;
600
- while (__HAL_I2C_GET_FLAG (handle , I2C_FLAG_RXNE ) == RESET ) {
638
+ while (! __HAL_I2C_GET_FLAG (handle , I2C_FLAG_RXNE )) {
601
639
if ((timeout -- ) == 0 ) {
602
640
return -1 ;
603
641
}
604
642
}
605
643
606
- return (int )i2c -> RXDR ;
644
+ /* Then Get Byte */
645
+ data = handle -> Instance -> RXDR ;
646
+
647
+ if (last ) {
648
+ /* Disable Address Acknowledge */
649
+ handle -> Instance -> CR2 |= I2C_CR2_NACK ;
650
+ }
651
+
652
+ return data ;
607
653
}
608
654
609
655
int i2c_byte_write (i2c_t * obj , int data ) {
610
656
struct i2c_s * obj_s = I2C_S (obj );
611
- I2C_TypeDef * i2c = (I2C_TypeDef * )obj_s -> i2c ;
612
657
I2C_HandleTypeDef * handle = & (obj_s -> handle );
613
- int timeout ;
614
-
615
- // Wait until the previous byte is transmitted
616
- timeout = FLAG_TIMEOUT ;
617
- while (__HAL_I2C_GET_FLAG (handle , I2C_FLAG_TXIS ) == RESET ) {
618
- if ((timeout -- ) == 0 ) {
619
- return 0 ;
658
+ int timeout = FLAG_TIMEOUT ;
659
+ uint32_t tmpreg = handle -> Instance -> CR2 ;
660
+ #if DEVICE_I2CSLAVE
661
+ if (obj_s -> slave ) {
662
+ return i2c_slave_write (obj , (char * ) & data , 1 );
663
+ }
664
+ #endif
665
+ if (obj_s -> pending_start ) {
666
+ obj_s -> pending_start = 0 ;
667
+ //* First byte after the start is the address */
668
+ tmpreg |= (uint32_t )((uint32_t )data & I2C_CR2_SADD );
669
+ if (data & 0x01 ) {
670
+ tmpreg |= I2C_CR2_START | I2C_CR2_RD_WRN ;
671
+ } else {
672
+ tmpreg |= I2C_CR2_START ;
673
+ tmpreg &= ~I2C_CR2_RD_WRN ;
674
+ }
675
+ /* Disable reload first to use it later */
676
+ tmpreg &= ~I2C_CR2_RELOAD ;
677
+ /* Disable Autoend */
678
+ tmpreg &= ~I2C_CR2_AUTOEND ;
679
+ /* Do not set any transfer size for now */
680
+ tmpreg |= (I2C_CR2_NBYTES & (1 << 16 ));
681
+ /* Set the prepared configuration */
682
+ handle -> Instance -> CR2 = tmpreg ;
683
+ } else {
684
+ /* Set the prepared configuration */
685
+ tmpreg = handle -> Instance -> CR2 ;
686
+
687
+ /* Then send data when there's room in the TX fifo */
688
+ if ((tmpreg & I2C_CR2_RELOAD ) != 0 ) {
689
+ while (!__HAL_I2C_GET_FLAG (handle , I2C_FLAG_TCR )) {
690
+ if ((timeout -- ) == 0 ) {
691
+ DEBUG_PRINTF ("timeout in byte_write\r\n" );
692
+ return 2 ;
693
+ }
694
+ }
620
695
}
696
+ /* Enable reload mode as we don't know how many bytes will eb sent */
697
+ tmpreg |= I2C_CR2_RELOAD ;
698
+ /* Set transfer size to 1 */
699
+ tmpreg |= (I2C_CR2_NBYTES & (1 << 16 ));
700
+ /* Set the prepared configuration */
701
+ handle -> Instance -> CR2 = tmpreg ;
702
+ /* Prepare next write */
703
+ timeout = FLAG_TIMEOUT ;
704
+ while (!__HAL_I2C_GET_FLAG (handle , I2C_FLAG_TXE )) {
705
+ if ((timeout -- ) == 0 ) {
706
+ return 2 ;
707
+ }
708
+ }
709
+ /* Write byte */
710
+ handle -> Instance -> TXDR = data ;
621
711
}
622
712
623
- i2c -> TXDR = (uint8_t )data ;
624
-
625
713
return 1 ;
626
714
}
627
715
#endif //I2C_IP_VERSION_V2
628
716
629
- void i2c_reset (i2c_t * obj ) {
630
- struct i2c_s * obj_s = I2C_S (obj );
631
- /* As recommended in i2c_api.h, mainly send stop */
632
- i2c_stop (obj );
633
- /* then re-init */
634
- i2c_init (obj , obj_s -> sda , obj_s -> scl );
635
- }
636
-
637
717
/*
638
718
* SYNC APIS
639
719
*/
0 commit comments