MCCI Trusted Bootloader
Simple trusted bootloader and tools for small embedded systems
mccibootloader_stm32l0_i2c_bus.c
Go to the documentation of this file.
1/*
2
3Module: mccibootloader_stm32l0_i2c_bus.c
4
5Function:
6 I2C bus driver code for STM32L0
7
8Copyright and License:
9 This file copyright (C) 2026 by
10
11 MCCI Corporation
12 3520 Krums Corners Road
13 Ithaca, NY 14850
14
15 See accompanying LICENSE file for copyright and license information.
16
17Author:
18 Terry Moore, MCCI Corporation July 2026
19
20*/
21
23
24#include "mcci_bootloader.h"
27#include "mcci_bootloader_device_internal.h"
28#include "mcci_stm32l0xx.h"
29#include "mcci_arm_cm0plus.h"
30
31#include <string.h>
32␌
33/****************************************************************************\
34|
35| Manifest constants & typedefs.
36|
37\****************************************************************************/
38
39#ifndef MCCI_BOOTLOADER_STM32L0_I2C_TIME_OUT_MS
40# define MCCI_BOOTLOADER_STM32L0_I2C_TIME_OUT_MS 100
41#endif
42
55
56static McciBootloaderDevice_BeginFn_t i2cBusBegin;
57static McciBootloaderDevice_EndFn_t i2cBusEnd;
58static McciBootloaderDeviceI2cBus_AddDeviceFn_t i2cBusAddDevice;
59static McciBootloaderDeviceI2cBus_ReadFn_t i2cBusRead;
60static McciBootloaderDeviceI2cBus_WriteFn_t i2cBusWrite;
61
62static McciBootloaderDeviceI2cDevice_ReadFn_t i2cDeviceRead;
63static McciBootloaderDeviceI2cDevice_WriteFn_t i2cDeviceWrite;
64
65static
66McciBootloaderDeviceI2cResult_t
69 );
70
71/****************************************************************************\
72|
73| Read-only data.
74|
75\****************************************************************************/
76
77static const McciBootloaderDeviceMethods_t i2cBus_deviceMethods =
78 {
79 .pBegin = i2cBusBegin,
80 .pEnd = i2cBusEnd
81 };
82
83static const McciBootloaderDeviceI2cBusMethods_t i2cBus_i2cBusMethods =
84 {
85 .pAddDevice = i2cBusAddDevice,
86 .pRead = i2cBusRead,
87 .pWrite = i2cBusWrite
88 };
89
90/// global config for I2C1. Linker discards this if not used.
91const McciBootloaderDeviceI2cBusStm32l0_Config_t gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c1 =
92 {
93 .baseAddress = MCCI_STM32L0_REG_I2C1,
94 .CCIPR_select =
95 {
98 },
101 };
102
103/// global config for I2C2. Linker discards this if not used.
104const McciBootloaderDeviceI2cBusStm32l0_Config_t gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c2 =
105 {
106 .baseAddress = MCCI_STM32L0_REG_I2C2,
107 .CCIPR_select =
108 {
109 .mask = 0, // I2C2 doesn't support clock selection
110 .value = 0 // value doesn't matter, since mask is zero.
111 },
114 };
115
116/// global config for I2C3. Linker discards this if not used.
117const McciBootloaderDeviceI2cBusStm32l0_Config_t gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c3 =
118 {
119 .baseAddress = MCCI_STM32L0_REG_I2C3,
120 .CCIPR_select =
121 {
124 },
127 };
128
129/// @brief I2C device node methods.
130///
131/// I2C device nodes are the equivalent of Windows PDOs; they are
132/// drivers, but they exist to export device-specific functionality
133/// from the parent bus driver to the function driver that uses
134/// the specific I2C device. Thus, we can null out the method functions
135/// as the framework behavior is sufficient.
136///
137static const McciBootloaderDeviceMethods_t i2cDevice_deviceMethods =
138 {
139 .pBegin = NULL,
140 .pEnd = NULL
141 };
142
143/// @brief I2C device accessor methods
144static const McciBootloaderDeviceI2cDeviceMethods_t i2cDevice_i2cDeviceMethods =
145 {
146 .pRead = i2cDeviceRead,
147 .pWrite = i2cDeviceWrite
148 };
149
150/****************************************************************************\
151|
152| Variables.
153|
154\****************************************************************************/
155
156␌
157/*
158
159Name: McciBootloader_Stm32L0Interface_initI2cBus()
160
161Function:
162 Initialize an I2C bus controller driver on an STM32L0.
163
164Definition:
165 McciBootloaderDeviceI2cBus_t *
166 McciBootloader_Stm32L0Interface_initI2cBus(
167 void *pRamForBus, // RAM to use for instance data
168 size_t sizeForBus, // size of RAM
169 const McciBootloaderDeviceI2cBusStm32l0_Config_t
170 *pConfig, // config of I2C block: selects controller,
171 // etc.
172 uint32_t timingr100k, // value to use for 100k operations
173 uint32_t timingr400k, // value to use for 400k operations
174 uint32_t timingr1M // value to use for 1MHz operations
175 );
176
177Description:
178 The device instance is initialized using the information passed in.
179 The actual pin assignment is left to the caller.
180
181 An alias is taken of pConfig.
182
183Returns:
184 Pointer to allocated and initialized device object.
185
186Notes:
187 For convenience, the library supplies appropriate McciBootloaderDeviceI2cBusStm32l0_Config_t
188 objects for I2C1, I2C2, and I2C3: gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c1,
189 gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c2 and
190 gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c3. Normally, clients will just
191 use one of these pre-cdefined values.
192
193*/
194
195McciBootloaderDeviceI2cBus_t *
197 void *pRamForBus,
198 size_t sizeForBus,
199 const McciBootloaderDeviceI2cBusStm32l0_Config_t *pConfig,
200 uint32_t timingr100k,
201 uint32_t timingr400k,
202 uint32_t timingr1M
203 )
204 {
205 // check parameters
206 if (sizeForBus < sizeof(McciBootloaderDeviceI2cBusStm32l0_t))
208
209 // 100k must be supported
212
213 // if 400k is not supported, 1m also must be "not supported"
217
218 if (pConfig == NULL)
219 {
221 }
222
223 // initialize the object
224 memset(pRamForBus, 0, sizeForBus);
225
226 // fill it in
227 McciBootloaderDeviceI2cBusStm32l0_t * const pI2cBus = pRamForBus;
228
229 pI2cBus->Device.pMethods = &i2cBus_deviceMethods;
230 pI2cBus->I2cBus.pMethods = &i2cBus_i2cBusMethods;
231 pI2cBus->Stm32l0.pConfig = pConfig;
232 pI2cBus->Stm32l0.timingr[McciBootloaderDeviceI2cSpeed_100k] = timingr100k;
233 pI2cBus->Stm32l0.timingr[McciBootloaderDeviceI2cSpeed_400k] = timingr400k;
234 pI2cBus->Stm32l0.timingr[McciBootloaderDeviceI2cSpeed_1M] = timingr1M;
235
236 // initialize
237 if (! McciBootloaderDevice_begin(&pI2cBus->DeviceCast))
239
240 return &pI2cBus->I2cBusCast;
241 }
242␌
243/*
244
245Name: McciBootloaderDeviceI2cBusStm32l0_t::i2cBusBegin()
246
247Function:
248 Initialize the I2C bus function and hardware.
249
250Definition:
251 static McciBootloaderDevice_BeginFn_t i2cBusBegin;
252
253 static bool
254 i2cBusBegin(
255 McciBootloaderDevice_t *pDevice
256 );
257
258Description:
259 Sets up the hardware for I2C operation.
260
261Returns:
262 true for success, false for failure
263
264Notes:
265 Cannot actually fail in this implementation.
266
267*/
268
269static bool
271 McciBootloaderDevice_t *pDevice
272 )
273 {
274 McciBootloaderDeviceI2cBusStm32l0_t * const pI2cBus = McciBootloaderDevice_getI2cBusStm32l0(pDevice);
275 uint32_t const baseAddress = pI2cBus->Stm32l0.pConfig->baseAddress;
276
277 // select the clock source
278 if (pI2cBus->Stm32l0.pConfig->CCIPR_select.mask != 0)
279 {
282 pI2cBus->Stm32l0.pConfig->CCIPR_select.mask,
283 pI2cBus->Stm32l0.pConfig->CCIPR_select.value
284 );
285 }
286
287 // enable the peripheral
290 pI2cBus->Stm32l0.pConfig->APB1ENR_mask
291 );
292
293 // reset it
296 pI2cBus->Stm32l0.pConfig->APB1RSTR_mask
297 );
298
299 // un-reset it
302 pI2cBus->Stm32l0.pConfig->APB1RSTR_mask
303 );
304
305 // set up timing register to default for 100kbps
307 baseAddress + MCCI_STM32L0_I2C_TIMINGR,
308 pI2cBus->Stm32l0.timingr[McciBootloaderDeviceI2cSpeed_100k]
309 );
310
311 return true;
312 }
313␌
314/*
315
316Name: McciBootloaderDeviceI2cBusStm32l0_t::i2cBusEnd()
317
318Function:
319 Deinitialize the I2C bus function and hardware.
320
321Definition:
322 static McciBootloaderDevice_EndFn_t i2cBusEnd;
323
324 static bool
325 i2cBusEnd(
326 McciBootloaderDevice_t *pDevice
327 );
328
329Description:
330 Tears down the hardware for I2C operation.
331
332Returns:
333 true for success, false for failure
334
335Notes:
336 Cannot actually fail in this implementation.
337
338*/
339
340static bool
342 McciBootloaderDevice_t *pDevice
343 )
344 {
345 McciBootloaderDeviceI2cBusStm32l0_t * const pI2cBus = McciBootloaderDevice_getI2cBusStm32l0(pDevice);
346 // uint32_t const baseAddress = pI2cBus->Stm32l0.pConfig->baseAddress;
347
348 // reset it
351 pI2cBus->Stm32l0.pConfig->APB1RSTR_mask
352 );
353
354 // un-reset it
357 pI2cBus->Stm32l0.pConfig->APB1RSTR_mask
358 );
359
360 // disable the peripheral
363 pI2cBus->Stm32l0.pConfig->APB1ENR_mask
364 );
365
366 return true;
367 }
368
369static McciBootloaderDeviceI2cResult_t
371 McciBootloaderDeviceI2cBus_t *pBus,
372 McciBootloaderDeviceI2cDevice_t *pDevice,
373 uint8_t *pBuffer,
374 size_t nBuffer,
375 size_t *pnActual
376 )
377 {
378 const size_t nBuffer_orig = nBuffer;
379 McciBootloaderDeviceI2cBusStm32l0_t * const pI2cBus = McciBootloaderDeviceI2cBus_getI2cBusStm32l0(pBus);
380 uint32_t const baseAddress = pI2cBus->Stm32l0.pConfig->baseAddress;
383 McciBootloaderDeviceI2cAddress_t const i2cAddress = pDevice->I2cDevice.address;
384 McciBootloaderDeviceI2cSpeed_t const bSpeed = pDevice->I2cDevice.bSpeed;
385
386 if (pnActual == NULL)
387 return McciBootloaderDeviceI2cResult_InvalidParameter;
388
389 if (nBuffer > 0xFF)
390 {
391 *pnActual = 0;
392 return McciBootloaderDeviceI2cResult_InvalidParameter;
393 }
394
395 // nBuffer == 0 is a read probe.
396
397 // compute CR2
398 uint32_t cr2;
399
404 ;
405
406 // set TIMINGR.
408 baseAddress + MCCI_STM32L0_I2C_TIMINGR,
409 pI2cBus->Stm32l0.timingr[bSpeed]
410 );
411
412 // enable
414 baseAddress + MCCI_STM32L0_I2C_CR1,
416 );
417
418 // write CR2
420 baseAddress + MCCI_STM32L0_I2C_CR2,
421 cr2
422 );
423
424 // set the start bit
426 baseAddress + MCCI_STM32L0_I2C_CR2,
428 );
429
430 // now, wait for RXNE to be set
432
435 {
437 {
439 break;
440 }
441
442 uint32_t const isr = McciArm_getReg(
443 baseAddress + MCCI_STM32L0_I2C_ISR
444 );
445
447 {
449 }
450
451 else if (isr & MCCI_STM32L0_I2C_ISR_RXNE && nBuffer != 0)
452 {
453 *pBuffer = (uint8_t) McciArm_getReg(baseAddress + MCCI_STM32L0_I2C_RXDR);
454 ++pBuffer, --nBuffer;
455
456 // restart the timer
458 }
459
460 else if (isr & MCCI_STM32L0_I2C_ISR_BERR)
461 {
462 // bus error. stop transfer now (though hw might be happy to go on).
464 }
465
466 else if (isr & MCCI_STM32L0_I2C_ISR_STOPF)
467 {
468 // STOPF and NACKF mean NACK error.
471 else
472 // AUTOEND: STOPF means we're done.
474 }
475
476 // NACKF without stop also means done, with error.
477 else if (isr & MCCI_STM32L0_I2C_ISR_NACKF)
478 {
480 }
481 // otherwise go on... we'll time out eventually
482 }
483
484 /* turn off the bus */
486 baseAddress + MCCI_STM32L0_I2C_CR1,
488 );
489
490 // return result.
491 *pnActual = nBuffer_orig - nBuffer;
492 return status_getResult(status);
493 }
494
495static McciBootloaderDeviceI2cResult_t
497 McciBootloaderDeviceI2cBus_t *pBus,
498 McciBootloaderDeviceI2cDevice_t *pDevice,
499 const uint8_t *pBuffer,
500 size_t nBuffer,
501 size_t *pnActual
502 )
503 {
504 const size_t nBuffer_orig = nBuffer;
505 McciBootloaderDeviceI2cBusStm32l0_t * const pI2cBus = McciBootloaderDeviceI2cBus_getI2cBusStm32l0(pBus);
506 uint32_t const baseAddress = pI2cBus->Stm32l0.pConfig->baseAddress;
509 McciBootloaderDeviceI2cAddress_t const i2cAddress = pDevice->I2cDevice.address;
510 McciBootloaderDeviceI2cSpeed_t const bSpeed = pDevice->I2cDevice.bSpeed;
511
512 if (pnActual == NULL)
513 return McciBootloaderDeviceI2cResult_InvalidParameter;
514
515 if (nBuffer > 0xFF)
516 {
517 *pnActual = 0;
518 return McciBootloaderDeviceI2cResult_InvalidParameter;
519 }
520
521 // nBuffer == 0 is a write probe
522
523 // compute cr2
524 uint32_t cr2;
525
529 ;
530
531 // set TIMINGR.
533 baseAddress + MCCI_STM32L0_I2C_TIMINGR,
534 pI2cBus->Stm32l0.timingr[bSpeed]
535 );
536
537 // enable
539 baseAddress + MCCI_STM32L0_I2C_CR1,
541 );
542
543 // write cr2
545 baseAddress + MCCI_STM32L0_I2C_CR2,
546 cr2
547 );
548
549 // set the start bit
551 baseAddress + MCCI_STM32L0_I2C_CR2,
553 );
554
555 // Initialize timeout and prepare for loop.
556 // These are essentially the precondition establishments
557 // of a for (;;) loop.
559
561
562 // wait for the bus busy indication to come on; that's different from "loop is busy"
563 // status.
565 {
567 {
569 break;
570 }
571
572 uint32_t const isr = McciArm_getReg(
573 baseAddress + MCCI_STM32L0_I2C_ISR
574 );
575
577 {
578 // go on to main loop.
579 break;
580 }
581
582 else if (isr & MCCI_STM32L0_I2C_ISR_ARLO)
583 {
585 }
586
587 else if (isr & MCCI_STM32L0_I2C_ISR_BERR)
588 {
590 }
591
592 else if (isr & MCCI_STM32L0_I2C_ISR_STOPF)
593 {
594 // detect stop+nack.
597 else
599 }
600
601 else if (isr & MCCI_STM32L0_I2C_ISR_NACKF)
602 {
604 }
605
606 // otherwise keep waiting for busy to come on.
607 }
608
610 {
612 {
614 break;
615 }
616
617 uint32_t const isr = McciArm_getReg(
618 baseAddress + MCCI_STM32L0_I2C_ISR
619 );
620
622 {
624 }
625
626 else if (isr & MCCI_STM32L0_I2C_ISR_BERR)
627 {
629 }
630
631 else if (isr & MCCI_STM32L0_I2C_ISR_STOPF)
632 {
633 // detect stop+nack.
636 else
638 }
639
640 else if (isr & MCCI_STM32L0_I2C_ISR_NACKF)
641 {
643 }
644
645 else if (isr & MCCI_STM32L0_I2C_ISR_TXE)
646 {
647 if (nBuffer == 0)
648 {
649 // we're waiting for STOPF due to AUTOEND.
650 }
651 else
652 {
653 McciArm_putReg(baseAddress + MCCI_STM32L0_I2C_TXDR, *pBuffer);
654 ++pBuffer, --nBuffer;
655
656 // restart the timer
658 }
659 }
660
661 // otherwise go on... we'll time out eventually
662 }
663
664 /* turn off the bus */
666 baseAddress + MCCI_STM32L0_I2C_CR1,
668 );
669
670 // return result.
671 *pnActual = nBuffer_orig - nBuffer;
672 return status_getResult(status);
673 }
674
675static
676McciBootloaderDeviceI2cResult_t
679 )
680 {
681 static const uint8_t k_map[] =
682 {
683 [McciBootloaderI2cBusStm32l0_Status_Busy] = McciBootloaderDeviceI2cResult_InternalError,
684 [McciBootloaderI2cBusStm32l0_Status_Done] = McciBootloaderDeviceI2cResult_OK,
685 [McciBootloaderI2cBusStm32l0_Status_Stopped] = McciBootloaderDeviceI2cResult_OK,
686 [McciBootloaderI2cBusStm32l0_Status_ArbitrationLost] = McciBootloaderDeviceI2cResult_ArbitrationLost,
687 [McciBootloaderI2cBusStm32l0_Status_Timeout] = McciBootloaderDeviceI2cResult_Timeout,
688 [McciBootloaderI2cBusStm32l0_Status_BusError] = McciBootloaderDeviceI2cResult_BusError,
689 [McciBootloaderI2cBusStm32l0_Status_NotBusy] = McciBootloaderDeviceI2cResult_BusError,
690 [McciBootloaderI2cBusStm32l0_Status_NackError] = McciBootloaderDeviceI2cResult_Nack,
691 };
692
693 // if this assert fails, make sure you've added all the status codes to k_map.
695
696 if (status < MCCIADK_LENOF(k_map))
697 return k_map[status];
698 else
699 return McciBootloaderDeviceI2cResult_InternalError;
700 }
701␌
702/*
703
704Name: i2cBusAddDevice()
705
706Function:
707 Implement McciBootloaderI2cBusAddDeviceFn_t method for STM32L0.
708
709Definition:
710 McciBootloaderDeviceI2cResult_t
711 i2cBusAddDevice(
712 McciBootloaderDeviceI2cBus_t *pBus,
713 McciBootloaderDeviceI2cDevice_t *pDevice,
714 size_t sizeDevice,
715 McciBootloaderDeviceI2cAddress_t i2cAddress,
716 McciBootloaderDeviceI2cSpeed_t i2cSpeed
717 );
718
719Description:
720 This function initializes the I2C device object at pDevice to operate
721 with the bus dirver at pBus. i2cAddress respresents the i2c address to be
722 used, and i2cSpeed represents the operating speed.
723
724 This function only sets up data structures. It does not actually probe the
725 bus, which does not need to be started yet.
726
727Returns:
728 McciBootloaderDeviceI2cResult_OK for success, some other result for failure.
729
730*/
731
732static McciBootloaderDeviceI2cResult_t
734 McciBootloaderDeviceI2cBus_t *pBusAbstract,
735 McciBootloaderDeviceI2cDevice_t *pDeviceAbstract,
736 size_t sizeDevice,
737 McciBootloaderDeviceI2cAddress_t i2cAddress,
738 McciBootloaderDeviceI2cSpeed_t i2cSpeed
739 )
740 {
741 McciBootloaderDeviceI2cBusStm32l0_t * const pBus =
743 McciBootloaderDeviceI2cDeviceStm32l0_t * const pDevice =
745
746 if (pDevice == NULL || sizeDevice < sizeof(*pDevice))
747 return McciBootloaderDeviceI2cResult_InvalidParameter;
748
749 memset(pDevice, 0, sizeof(*pDevice));
750
751 if (i2cSpeed >= MCCIADK_LENOF(pBus->Stm32l0.timingr))
752 return McciBootloaderDeviceI2cResult_InvalidParameter;
753
754 // decrement speed if we find an invalid speed.
755 // timingr[0] must not be MCCI_BOOTLOADER_STM32L0_I2C_TIMINGR_NOT_SUPPORTED
756 while (pBus->Stm32l0.timingr[i2cSpeed] == MCCI_BOOTLOADER_STM32L0_I2C_TIMINGR_NOT_SUPPORTED)
757 {
758 if (i2cSpeed == 0)
759 return McciBootloaderDeviceI2cResult_InternalError;
760
761 --i2cSpeed;
762 }
763
764 if (i2cAddress >= 0x80)
765 {
766 // not supporting 10-bit addresses yet.
767 return McciBootloaderDeviceI2cResult_InvalidParameter;
768 }
769
770 // set methods, which means device is now initialized.
771 pDevice->Device.pMethods = &i2cDevice_deviceMethods;
772
773 // set class methods
774 pDevice->I2cDevice.pMethods = &i2cDevice_i2cDeviceMethods;
775
776 // set the device information.
777 pDevice->I2cDevice.address = i2cAddress;
778 pDevice->I2cDevice.bSpeed = i2cSpeed;
779 pDevice->I2cDevice.pBus = &pBus->I2cBusCast;
780
781 return McciBootloaderDeviceI2cResult_OK;
782 }
783
784static McciBootloaderDeviceI2cResult_t
786 McciBootloaderDeviceI2cDevice_t *pI2cDevice,
787 uint8_t *pBuffer,
788 size_t nBuffer,
789 size_t *pnActual
790 )
791 {
792 return (*pI2cDevice->I2cDevice.pBus->I2cBus.pMethods->pRead)(
793 pI2cDevice->I2cDevice.pBus,
794 pI2cDevice,
795 pBuffer,
796 nBuffer,
797 pnActual
798 );
799 }
800
801static McciBootloaderDeviceI2cResult_t
803 McciBootloaderDeviceI2cDevice_t *pI2cDevice,
804 const uint8_t *pBuffer,
805 size_t nBuffer,
806 size_t *pnActual
807 )
808 {
809 return (*pI2cDevice->I2cDevice.pBus->I2cBus.pMethods->pWrite)(
810 pI2cDevice->I2cDevice.pBus,
811 pI2cDevice,
812 pBuffer,
813 nBuffer,
814 pnActual
815 );
816 }
817
818/**** end of mccibootloader_stm32l0_i2c_bus.c ****/
static uint32_t McciArm_putRegOr(uint32_t reg, uint32_t orVal)
or 32-bit values to a cm0plus register
static uint32_t McciArm_getReg(uint32_t reg)
read a 32-bit value from a cm0plus register
static uint32_t McciArm_putReg(uint32_t reg, uint32_t val)
write a 32-bit value to a cm0plus register
static uint32_t McciArm_putRegClear(uint32_t reg, uint32_t clearVal)
clear out 32-bit values to a cm0plus register
static uint32_t McciArm_putRegMasked(uint32_t reg, uint32_t maskVal, uint32_t modVal)
store to cm0plus register under mask
@ McciBootloaderError_I2cBegin
I2c bus failed begin.
@ McciBootloaderError_InternalConsistency
an internal consistency check failed.
#define MCCI_BOOTLOADER_FIELD_SET_VALUE(fmask, val)
static McciBootloaderDeviceI2cBusStm32l0_t * McciBootloaderDeviceI2cBus_getI2cBusStm32l0(McciBootloaderDeviceI2cBus_t *pDevice)
upcast from i2c controller device to enclosing McciBootloaderDeviceI2cBusStm32l0_t
#define MCCI_BOOTLOADER_STM32L0_I2C_TIMINGR_NOT_SUPPORTED
value to use for timing parameters when a speed is not supported.
static McciBootloaderDeviceI2cBusStm32l0_t * McciBootloaderDevice_getI2cBusStm32l0(McciBootloaderDevice_t *pDevice)
upcast from device to enclosing McciBootloaderDeviceI2cBusStm32l0_t
static McciBootloaderDeviceI2cDeviceStm32l0_t * McciBootloaderDeviceI2cDevice_getI2cDeviceStm32l0(McciBootloaderDeviceI2cDevice_t *pDevice)
upcast from i2c controller device to enclosing McciBootloaderDeviceI2cDeviceStm32l0_t
static McciBootloader_Milliseconds_t McciBootloaderPlatform_getMilliseconds(void)
void MCCI_BOOTLOADER_NORETURN_PFX McciBootloaderPlatform_fail(McciBootloaderError_t errorCode) MCCI_BOOTLOADER_NORETURN_SFX
MCCIADK_C_ASSERT(sizeof(McciBootloaderPlatform_ARMv6M_SvcError_t)==sizeof(uint32_t))
uint32_t McciBootloader_Milliseconds_t
Time (in milliseconds)
#define MCCI_STM32L0_REG_RCC_APB1RSTR_I2C1RST
#define MCCI_STM32L0_I2C_CR2_NBYTES
number of bytes [7:0]
#define MCCI_STM32L0_REG_RCC_APB1RSTR_I2C2RST
#define MCCI_STM32L0_I2C_ISR_BERR
bus error
#define MCCI_STM32L0_REG_RCC_CCIPR_I2C3SEL
#define MCCI_STM32L0_REG_I2C2
Section 27.7.12: I2C register map (1K)
#define MCCI_STM32L0_REG_RCC_APB1ENR_I2C3EN
#define MCCI_STM32L0_I2C_ISR_STOPF
STOP detection flag.
#define MCCI_STM32L0_I2C_TXDR
Section 27.7.11: transmit data register.
#define MCCI_STM32L0_REG_RCC_APB1RSTR
APB1 peripheral reset.
#define MCCI_STM32L0_I2C_ISR_BUSY
bus busy
#define MCCI_STM32L0_REG_RCC_CCIPR_I2C3SEL_HSI16
#define MCCI_STM32L0_REG_RCC_CCIPR_I2C1SEL_HSI16
#define MCCI_STM32L0_I2C_CR2_AUTOEND
automatic end mode (master)
#define MCCI_STM32L0_REG_I2C3
Section 27.7.12: I2C register map (1K)
#define MCCI_STM32L0_REG_RCC_CCIPR
Clock configuration CCIPR.
#define MCCI_STM32L0_I2C_RXDR
Section 27.7.10: receive data register.
#define MCCI_STM32L0_I2C_CR1
Section 27.7.1: control register 1.
#define MCCI_STM32L0_I2C_TIMINGR
Section 27.7.5: timing register.
#define MCCI_STM32L0_REG_RCC_APB1ENR_I2C2EN
#define MCCI_STM32L0_REG_RCC_APB1RSTR_I2C3RST
#define MCCI_STM32L0_I2C_ISR_ARLO
arbitration lost
#define MCCI_STM32L0_REG_RCC_APB1ENR_I2C1EN
#define MCCI_STM32L0_I2C_ISR_RXNE
receive data register not empty
#define MCCI_STM32L0_I2C_ISR
Section 27.7.7: interrupt and status register.
#define MCCI_STM32L0_I2C_CR2_SADD
slave address [9:0]
#define MCCI_STM32L0_I2C_CR2
Section 27.7.2: control register 2.
#define MCCI_STM32L0_I2C_CR2_START
START generation.
#define MCCI_STM32L0_I2C_CR2_RD_WRN
transfer direction: 1=read, 0=write
#define MCCI_STM32L0_I2C_CR1_PE
peripheral enable
#define MCCI_STM32L0_I2C_ISR_NACKF
not acknowledge received flag
#define MCCI_STM32L0_I2C_ISR_TXE
transmit data register empty
#define MCCI_STM32L0_REG_RCC_APB1ENR
APB1 peripheral clock enable.
#define MCCI_STM32L0_REG_RCC_CCIPR_I2C1SEL
#define MCCI_STM32L0_REG_I2C1
Section 27.7.12: I2C register map (1K)
static McciBootloaderDeviceI2cDevice_ReadFn_t i2cDeviceRead
static const McciBootloaderDeviceMethods_t i2cDevice_deviceMethods
I2C device node methods.
const McciBootloaderDeviceI2cBusStm32l0_Config_t gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c2
global config for I2C2. Linker discards this if not used.
const McciBootloaderDeviceI2cBusStm32l0_Config_t gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c3
global config for I2C3. Linker discards this if not used.
#define MCCI_BOOTLOADER_STM32L0_I2C_TIME_OUT_MS
static McciBootloaderDevice_BeginFn_t i2cBusBegin
static McciBootloaderDeviceI2cResult_t status_getResult(McciBootloaderI2cBusStm32l0_Status_t status)
static const McciBootloaderDeviceMethods_t i2cBus_deviceMethods
@ McciBootloaderI2cBusStm32l0_Status_Done
@ McciBootloaderI2cBusStm32l0_Status_Timeout
@ McciBootloaderI2cBusStm32l0_Status_ArbitrationLost
@ McciBootloaderI2cBusStm32l0_Status_Busy
@ McciBootloaderI2cBusStm32l0_Status_NotBusy
@ McciBootloaderI2cBusStm32l0_Status_BusError
@ McciBootloaderI2cBusStm32l0_Status_Stopped
@ McciBootloaderI2cBusStm32l0_Status_NackError
@ McciBootloaderI2cBusStm32l0_Status__MAX
muat always be last, for error checking.
static McciBootloaderDeviceI2cBus_WriteFn_t i2cBusWrite
static McciBootloaderDeviceI2cBus_ReadFn_t i2cBusRead
static McciBootloaderDeviceI2cDevice_WriteFn_t i2cDeviceWrite
static McciBootloaderDeviceI2cBus_AddDeviceFn_t i2cBusAddDevice
static McciBootloaderDevice_EndFn_t i2cBusEnd
static const McciBootloaderDeviceI2cBusMethods_t i2cBus_i2cBusMethods
static const McciBootloaderDeviceI2cDeviceMethods_t i2cDevice_i2cDeviceMethods
I2C device accessor methods.
McciBootloaderDeviceI2cBus_t * McciBootloader_Stm32L0Interface_initI2cBus(void *pRamForBus, size_t sizeForBus, const McciBootloaderDeviceI2cBusStm32l0_Config_t *pConfig, uint32_t timingr100k, uint32_t timingr400k, uint32_t timingr1M)
Initialize an I2C bus controller driver on an STM32L0.
const McciBootloaderDeviceI2cBusStm32l0_Config_t gk_McciBootloaderDeviceI2cBusStm32l0_Config_I2c1
global config for I2C1. Linker discards this if not used.