Вот например, что работает в Keil у меня:
CODE
// 24c32.h
#ifndef _24C32_H_
#define _24C32_H_
#define EEPROM_PAGE_SIZE 32
//
int readBytesFrom24C32( unsigned int eepromStartAddr, unsigned char * dest, unsigned int bytesToRead );
//
int i2cSavePagesTo24C32( unsigned int eepromStartPageAddr, unsigned char * src, unsigned int pagesToWrite );
#endif
CODE
; 24c32.s
AREA TEXT, CODE, READONLY
ARM
EXPORT readBytesFrom24C32
; read bytes from 24C32
; IN
; r0 - start address in 24C32
; r1 - target buffer address in memory
; r2 - bytes count
; OUT
; r0 - error state, == 0 if no errors
readBytesFrom24C32
stmfd SP!, {r1,r2,r5-r11,LR}
; prepare transfer address and work constants
bl i2cSetTransferAddress
; check result
tst r8, r8
movne r0, r8
bne readBytesFrom24C32_exit
; set another start condition
bl i2cMakeStart
; check result
tst r8, r8
movne r0, r8
bne readBytesFrom24C32_exit
; send address with /WR=1
ldr r9, =0xA1
bl i2cSendByte
; get ACK
bl i2cReadAckState
bne readBytesFrom24C32_deviceNotFound
; read one byte
readBytesFrom24C32_loop
bl i2cRecvByte
; store byte to buffer
strb r9, [r1], #1
; send ACK or NACK
cmp r2, #1
; drop SDA to 0 if need receive more bytes
strne r6, [r7, #PIO_OER]
; rise SDA to 1 if it was last byte
streq r6, [r7, #PIO_ODR]
; pulse SCL
str r5, [r7, #PIO_ODR] ; SCL = 1
bl i2cDelay
str r5, [r7, #PIO_OER] ; SCL = 0
bl i2cDelay
; loop
subs r2, r2, #1
bne readBytesFrom24C32_loop
; make stop
; rise SCL up
str r5, [r7, #PIO_ODR] ; SCL = 1
bl i2cDelay
; rise SDA up
str r6, [r7, #PIO_ODR] ; SDA = 1
bl i2cDelay
ldr r0, =0
readBytesFrom24C32_exit
ldmfd SP!, {r1,r2,r5-r11,PC}
readBytesFrom24C32_deviceNotFound
ldr r0, =ERR_I2C_DEVICE_NOT_FOUND
b readBytesFrom24C32_exit
EXPORT i2cSavePagesTo24C32
; save 1 or more pages (32 bytes per page) to EEPROM
; IN
; r0 - start address in EEPROM (32 bytes aligned!)
; r1 - source buffer in local memory
; r2 - pages count
; OUT
; r0 - error state, = 0 if no errors
i2cSavePagesTo24C32
stmfd SP!, {r1,r2,r5-r12,LR}
i2cSavePagesTo24C32_loop
; tries count
ldr r12, =120
i2cSavePagesTo24C32_waitLoop
; prepare transfer address and work constants
bl i2cSetTransferAddress
; check result
tst r8, r8
beq i2cSavePagesTo24C32_sendPage
subs r12, r12, #1
bne i2cSavePagesTo24C32_waitLoop
;ldr r0, =ERR_WRITE_PAGE_TIMEOUT
mov r0, r8
b i2cSavePagesTo24C32_exit
i2cSavePagesTo24C32_sendPage
; send page
ldr r12, =EEPROM_24C32_PAGE_SIZE
i2cSavePagesTo24C32_pageLoop
ldrb r9, [r1], #1
bl i2cSendByte
; get ACK
bl i2cReadAckState
ldrne r0, =ERR_I2C_ACK_NOT_RECEIVED
bne i2cSavePagesTo24C32_exit
; next byte
subs r12, r12, #1
bne i2cSavePagesTo24C32_pageLoop
; make stop
; drop SDA down
str r6, [r7, #PIO_OER] ; SDA = 0
bl i2cDelay
; rise SCL up
str r5, [r7, #PIO_ODR] ; SCL = 1
bl i2cDelay
; rise SDA up
str r6, [r7, #PIO_ODR] ; SDA = 1
bl i2cDelay
; next page addr
add r0, r0, #EEPROM_24C32_PAGE_SIZE
; next page loop
subs r2, r2, #1
bne i2cSavePagesTo24C32_loop
; delay after last page write
ldr r12, =71000
i2cSavePagesTo24C32_delayLoop
subs r12, r12, #1
bne i2cSavePagesTo24C32_delayLoop
ldr r0, =0
i2cSavePagesTo24C32_exit
ldmfd SP!, {r1,r2,r5-r12,PC}