I am trying to write an STM32 as an I2C slave device with a simple interface that works like this:
So master will always send a registered address every time, then either write or read from that register address.
The slave then needs to always receive 1 byte for a registered address, then it either sends what information is in that register back to the master if the next operation is a read or overwrites the register if the master's next operation is another write.
When I run my code however, I get some NACKS where ther should be ACKS
Here is the response when the master requests a buffer:
You can see the NACK at the end right after the slave finishes sending the last byte
This is a bit of a pain but the master receives the data ok so i can live with this
However when i try to write to a register on the slave this is what comes out:
Slave receives register address, then receives 1 byte and ack, then after receiving the second byte for some reason it just holds the line up (I need to use clock stretching here)
This is not ok, not only the slave didnt receive all the data but it also locks the line for any further communications. Why Am i having this? im scratching my head for months on this at this point
Here is the master code just for reference (running on a simple Arduino) since the focus is really on the STM32 slave code:
#include <Wire.h>
uint16_t read_register(int devAddr, unsigned char regAddr, unsigned char bytes, unsigned char * buffer){
unsigned char i = 0;
Wire.beginTransmission(devAddr);
Wire.write(regAddr);
Wire.endTransmission(false);
Wire.requestFrom(devAddr, bytes , true);
while(Wire.available()){
buffer[i] = Wire.read();
i++;
}
return true;
}
uint16_t write_register(int devAddr, unsigned char regAddr, unsigned char bytes, unsigned char * buffer){
unsigned char i = 0;
Wire.beginTransmission(devAddr);
Wire.write(regAddr); // Reg to write
for(i = 0; i < bytes; i++){
Wire.write(buffer[i]);
}
Wire.endTransmission(true);
return true;
}
void setup()
{
Wire.begin();
Wire.setClock(400);
Serial.begin(9600);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("Starting");
}
void loop()
{
unsigned char buffSize = 4;
unsigned char readBuff[buffSize];
unsigned char writeBuff[5] = {0xFB, 0xE3, 0XE2, 0xE1, 0xE0};
for (int i = 0; i < buffSize; i++) readBuff[i] = 0;
read_register(0x1F, 251, buffSize, readBuff);
Serial.print(readBuff[3], HEX);
Serial.print(readBuff[2], HEX);
Serial.print(readBuff[1], HEX);
Serial.println(readBuff[0], HEX);
write_register(0x1F, 0xFB, 5, writeBuff);
delay(2000);
}
Here is the I2C code section of the STM32 slave:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file i2c.c
* #brief This file provides code for the configuration
* of the I2C instances.
******************************************************************************
* #attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "i2c.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
I2C_HandleTypeDef hi2c1;
/* I2C1 init function */
void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
// Get I2C address code from hardware jumpers
// Address starts at I2C_ADDRESS_BASE and is offset by value read on jumpers array
uint8_t I2C_Address = 0x0;
I2C_Address = (I2C_ADDRESS_BASE + (
(HAL_GPIO_ReadPin(AD0_GPIO_Port, AD0_Pin) << 0)|
(HAL_GPIO_ReadPin(AD1_GPIO_Port, AD1_Pin) << 1)|
(HAL_GPIO_ReadPin(AD2_GPIO_Port, AD2_Pin) << 2)|
(HAL_GPIO_ReadPin(AD3_GPIO_Port, AD3_Pin) << 3)
)) << 1;
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x0000020B;
hi2c1.Init.OwnAddress1 = I2C_Address;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_ENABLE;
hi2c1.Init.OwnAddress2 = (I2C_ADDRESS_BASE + 16) << 1;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
/* I2C1 interrupt Deinit */
HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
#define I2C_BUFFER_SIZE 8
uint8_t i2c_buffer[I2C_BUFFER_SIZE];
uint8_t reg_addr_rcvd = 0;
#define I2C_REG_ADD_SIZE 1
#define I2C_PAYLOAD_SIZE 4
extern void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode){
UNUSED(AddrMatchCode);
// If is master write, listen to necessary amount of bytes
if(TransferDirection == I2C_DIRECTION_TRANSMIT){
// First write request is always 1 byte of the requested reg address
// Will saved it on the first position of I2C_buffer
if(!reg_addr_rcvd){
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, (void*)i2c_buffer, I2C_REG_ADD_SIZE, I2C_FIRST_FRAME);
} else {
// If a subsequent write request is sent, will receve 4 bytes from master
// Save it on the rest of the buffer
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, (void*)i2c_buffer, I2C_PAYLOAD_SIZE, I2C_NEXT_FRAME);
}
}
else {
// If a read request is sent by the master, return the value of the data in the requested register that was saved on 1st
// position of the I2C buffer
HAL_I2C_Slave_Sequential_Transmit_IT(hi2c, data_register[i2c_buffer[0]].mem_addr, data_register[i2c_buffer[0]].len, I2C_LAST_FRAME);
}
// Read address + data size. If it is a read command, data size will be zero
}
extern void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c){
// This is called after a master 'write' request. first time around it will be a register.
// Second time if its a write to register request, it will be a payload
if(!reg_addr_rcvd){
// If reg_addr_rcvd is false, means that it received a register
reg_addr_rcvd = 1;
} else {
// If reg_addr_rcvd is set, means that this callback was returned after the payload data has been received
reg_addr_rcvd = 0;
}
HAL_I2C_EnableListen_IT(hi2c);
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);
}
extern void HAL_I2C_ListenCpltCallback (I2C_HandleTypeDef *hi2c){
HAL_I2C_EnableListen_IT(hi2c);
HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin);
}
extern void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c){
// Reset reg_addr_rcvd after finish sending requested register
reg_addr_rcvd = 0;
HAL_I2C_EnableListen_IT(hi2c);
}
extern void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin);
//HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */
//HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */
//HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */
//HAL_I2C_ERROR_AF 0x00000004U /*!< Ack Failure error */
//HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */
//HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */
//HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */
uint32_t error_code = HAL_I2C_GetError(hi2c);
if (error_code != HAL_I2C_ERROR_AF){}
HAL_I2C_EnableListen_IT(hi2c);
}
/* USER CODE END 1 */
And here is cubeMX config for the I2C slave
Appreciate any insigth you guys could have.
Thank you!
You have asked two questions. This is an answer to the first question, which is why do you get a nack after reading 4 data bytes?
This is the absolutely correct and expected behaviour, and anyway it is being done by the Arduino not the STM32.
To explain: the ack after each byte is always the responsibility of the side that didn't send the byte. When the master writes an address or data to the slave, the slave generates an ack if it received the byte and is ready for the master to start sending the next byte.
When the master reads data from the slave, the slave (STM32) sends the data byte, and it is the responsibility of the master (Arduino) to choose to send an ack or nack. If the master sends an ack it means "I have received this byte, prepare to send me another byte". If the master sends nack it means "I have finished getting data from to you".
It is perfectly legal in I2C to start reading without knowing how many bytes you want, in this case you will ack every byte and then send a stop condition when you have read enough. In your case however, you told the Arduino up front that it should read 4 bytes, so it proceeds to ack the first three and nacks the fourth.
In some cases this behaviour can save resources at the slave end because the slave knows straight away that it doesn't have to get a fifth byte ready.
You have asked two questions. This is an answer to the second question, which is why doesn't the STM32 slave ack more bytes written to it but instead stretch the clock?
In your ADDR interrupt function, if you have not received a register address, (reg_addr_rcvd is false) you start a receive of one byte. The master (Arduino) sends this one byte, and presumably the receive complete callback occurs.
If at this point the Arduino were to send a restart or a stop-start and the slave address again, then the ADDR interrupt would occur again, and upon finding reg_addr_rcvd true it would start a receive of 4 bytes, which would all be acked.
However, the Arduino doesn't send a restart, it just carries on blasting out the data straight after the register address. This is a perfectly normal and reasonable for a master to do. You need to handle both cases correctly. Probably this means starting a receive of data in the receive-complete interrupt once the register address is received. If you don't start a receive then the I2C peripheral will just stretch the clock because it has nowhere to put the data that has been buffered.
To write robust production quality software you also need to handle various other combinations. Eg: if the master sends more than 4 data bytes you will get never-ending stretching again. If the master sends a stop after less than 4 bytes then you need to be able to abort the receive and go back to listening etc.
I'm trying to understand how the STM32F091VB manages the send of data via serial protocol with the function HAL_UART_Transmit_IT()
At the moment I've a function called in the main() that creates the packet and send it via serial; it is something like this:
tx1[0] = STX;
tx1[1] = 0xFF;
tx1[2] = 0x80;
tx1[3] = 0x80;
DE_TAST_HIGH;
HAL_UART_Transmit_IT(&huart3, tx1, 8);
Now, the data I'm sending is quite small so the code run pretty fast and I'm trying to understand what's going to happen if I try to send a huge packet via serial protocol.
For istance, if my tx1[] is 100byte the HAL_UART_Transmit_IT() function block the CPU waiting while the full packet is sent to the serial port or it works more like a separate process where I tell the micro to send that packet and, while sending it it also process the remaining part of my code/main function?
I've tried to search on the micro datasheet to see if there was something about this process but I had no luck. I've read the stm32f0xx_hal_uart.c and it confirms that it is sent via interrupt in a non blocking mode but I would like to have some more in depth documentation about it
First of all you need to understand how the HAL_UART_Transmit_IT is meant to be used. We can get some help from STM FAQ.
The function is "non blocking" because when you call it it will do some configuration of the interrupts and then return. The buffer will not be transmitted during the call to your function, instead the heavy lifting is deferred to a later stage.
We can further have a look at the source code, to get a proof from what I said (note I kept only the juicy parts).
Blocking
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
uint16_t* tmp;
uint32_t tickstart = 0U;
// [ ... ]
huart->TxXferSize = Size;
huart->TxXferCount = Size;
while(huart->TxXferCount > 0U)
{
// [ ... ]
// This is were the actual HW regs are accessed, starting the transfer
huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
}
}
// [ ... ]
return HAL_OK
}
Non Blocking
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
/* Enable the UART Transmit data register empty Interrupt */
// This is the only part were HW regs are accessed. What is happening here??
SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
return HAL_OK;
}
The _IT function only activates one interrupt, based also on the datasheet:
This means we will receive an interrupt whenever the TX buffer is free. Who is actually sending the data then?
With the help of the FAQs and reading the source code, we find that void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) does something like this:
/* UART in mode Transmitter ------------------------------------------------*/
if(((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
UART_Transmit_IT(huart);
return;
}
Which in turn calls the UART_Transmit_IT
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
/* Check that a Tx process is ongoing */
if(huart->gState == HAL_UART_STATE_BUSY_TX)
{
huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF);
if(--huart->TxXferCount == 0U)
{
/* Disable the UART Transmit Complete Interrupt */
CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
/* Enable the UART Transmit Complete Interrupt */
SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
This function transmits only one byte! It then decrements the counter for the transmission (remember, all the information was set into the uart handler) and if it reaches 0, finally the complete interrupt is called.
Interrupts
Note that StmCube does the peripheral initialization and interrupt linking for you, but if you program from scratch you need to remember to write and register UART_IRQ_Handler
You can find here the code navigator to review my snippets and investigate further.
at the beginning, I'm relatively new to the world of microcontroller programming.
I am preparing a program for stable communication between the STM32 and a PC equipped with Matlab. Currently I've managed to create a connection between Matlab and STM32 (F303RE board) but it works unstable. Communication was based on interruptions (both receiving and sending information). My code on STM32:
Main:
int main(void)
{
HAL_Init();
SystemClockConfig();
UART2_Init();
HAL_UART_Receive_IT(&huart2, &rcvd_data, 1);
while (1)
{
Print_CAN_Frame("Tx", IPC_Ligths.ID, IPC_Ligths.DLC, IPC_Ligths.CAN_Tx);
HAL_Delay(3000);
/*
Section for handling incoming information by UART
while((flag_UART_RX_COMPLETED && flag_UART_TX_COMPLETED) == TRUE)
{
parseFromUART(data_buffer);
saveDataToFrame(canUartBuffer);
ClearArray(data_buffer, 70);
count = 0;
flag_UART_RX_COMPLETED = FALSE;
flag_UART_TX_COMPLETED = FALSE;
}
*/
}
return 0;
}
Callbacks
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (rcvd_data == '\r') {
data_buffer[count++] = '\r';
flag_UART_RX_COMPLETED = TRUE;
if (HAL_UART_Transmit_IT(&huart2, data_buffer, count) != HAL_OK)
{
Error_handler();
}
}
else
{
data_buffer[count++] = rcvd_data;
}
HAL_UART_Receive_IT(&huart2, &rcvd_data, 1);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
flag_UART_TX_COMPLETED = TRUE;
}
and interrupts hanlders:
void SysTick_Handler (void)
{
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
}
void USART2_IRQHandler (void)
{
HAL_UART_IRQHandler(&huart2);
}
The code from matlab.
Function to send data via UART (I want a nice CAN frame to show me on the serial port monitor)
function statusCode = CANsend(ID, DLC, BUFFER)
% Function to send CAN data by USART port to STM32.
% Data sended by this function will be avaiable via Serial Port Monitor
% ***** PARAMETERS *****
% ID - CAN frame identifier
% DLC - CAN frame data length code
% BUFFER - CAN frame data buffer(array) in HEX - f.e. [0xAA, 0xBB]
global serialPortConfiguration
flag = true;
UARTstring = ParseDataForUART(ID,DLC,BUFFER);
writeline(serialPortConfiguration,UARTstring);
% Check until STM32 give echo for given frame (frame accepted)
while flag
receivedData = readline(serialPortConfiguration);
if ( char(receivedData) == UARTstring)
flag = false;
statusCode = "Data Send Succeded";
disp(UARTstring);
pause(0.1)
else
pause(0.1)
writeline(serialPortConfiguration,UARTstring);
end
end
end
and function to configure communication via UART in Matlab:
function InitializeCommunication(portNumber,baudRate)
% Function to configure basic USART communication paramters
% portNumber: number of serial port (f.e: 'COM5', 'COM10')
% baudRate: baud rate for communication (default 115200)
% example: InitializeCommunication('COM10',115200)
global serialPortConfiguration
serialPortConfiguration = serialport(portNumber,baudRate);
configureTerminator(serialPortConfiguration,"CR");
end
What is this strange behavior? First of all, after sending several frames through the CANsend function in matlab (e.g. 15 - 20). the program stops into HAL_GetTick or I have UART Over-Run error. When I uncomment in the main function the part of the code responsible for handling incoming frames the program crash after sending the first message. Apart from sending data by Matlab I'm also sending data for debugging by TeraTerm and there everything seems to work much more stable (although not identical). Do you have any ideas what could be wrong? Maybe changing the approach and implementation by DMA will help?
I am using an MSP430 and writing code in C. I am receiving characters (working) via UART and placing them into an array rxDataArray. Since I am using an MSP430G2211, I have limited memory. The maximum array size is 50 and any more it won't build/load and says out of space.
My MSP430 is communicating to a ESP8266 module (wifi) where I am using "AT" commands. I am receive an echo of my AT command, followed by a response (ex. AT+RST responds with AT+RST...ok). I am confused using C, how I can make a string with just the "ok" response and check if it worked correctly. I have the data in the array, just not sure how to pick certain elements of the array, make a string, and compare that to "ok" response. I am used to using CString in C++ and am confused how to do this in C.
/--------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//-------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMERA1_VECTOR
__interrupt void Timer_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMERA1_VECTOR))) Timer_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{
static unsigned char rxBitCnt = 8;
static unsigned char rxData = 0;
switch (__even_in_range(TAIV, TAIV_TAIFG)) { // Use calculated branching
case TAIV_TACCR1: // TACCR1 CCIFG - UART RX
TACCR1 += UART_TBIT; // Add Offset to CCRx
if (TACCTL1 & CAP) { // Capture mode = start bit edge
TACCTL1 &= ~CAP; // Switch capture to compare mode
TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0
}
else {
rxData >>= 1;
if (TACCTL1 & SCCI) { // Get bit waiting in receive latch
rxData |= 0x80;
}
rxBitCnt--;
if (rxBitCnt == 0) { // All bits RXed?
rxBuffer = rxData; // Store in global variable
if (rxDataCnt < 50)
{
rxDataArray[rxDataCnt] = rxBuffer;
rxDataCnt++;
}
else
{
int i = 0;
for (i; i<50-1; i++)
{
rxDataArray[i] = rxDataArray[i+1];
}
rxDataArray[50-1] = rxBuffer;
}
rxBitCnt = 8; // Re-load bit counter
TACCTL1 |= CAP; // Switch compare to capture mode
__bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR)
}
}
break;
}
}
//-----------------------------------------------------------------------
You can turn OFF echo by sending ATE0 command.
Also to find the intended string response please follow below steps:
Enable UART Transmit and Receive Interrupt.
After completing your command transmission you will start receiving data in UART ISR.
In the receive interrupt start a timer of say 1 second(You need to consider baud-rate for exact calculation).
Make track of number of received bytes in UART ISR.
Now after timer expires add null to end of last received byte in buffer.
Now,You can use string manipulation functions of C to find the intended response.
I am trying to write a device code for C8051F340 to get the data from the host(PC) via USB. I have some example from silicon lab and the code look like below:
void Receive_File(void)
{
ReadStageLength = ((BytesToRead - BytesRead) > MAX_BLOCK_SIZE_READ)? MAX_BLOCK_SIZE_READ:(BytesToRead - BytesRead);
BytesRead += Block_Read((U8*)(&TempStorage[BlockIndex]), ReadStageLength); // Read Block
BlockIndex++;
// If device has received as many bytes as fit on one FLASH page, disable interrupts,
// write page to flash, reset packet index, enable interrupts
// Send handshake packet 0xFF to host after FLASH write
if ((BlockIndex == (BLOCKS_PR_PAGE)) || (BytesRead == BytesToRead))
{
Page_Erase((U8*)(PageIndices[PageIndex]));
Page_Write((U8*)(PageIndices[PageIndex]));
PageIndex++;
Led1 = !Led1;
BlockIndex = 0;
Buffer[0] = 0xFF;
Block_Write(Buffer, 1); // Send handshake Acknowledge to host
}
// Go to Idle state if last packet has been received
if (BytesRead == BytesToRead) {M_State = ST_IDLE_DEV; Led1 = 0;}
}
// Startup code for SDCC to disablt WDT before initializing variables so that
// a reset does not occur
#if defined SDCC
void _sdcc_external_startup (void)
{
PCA0MD &= ~0x40; // Disable Watchdog timer
}
#endif
I have some questions want to ask:
1. Where the data goes? the Buffer [0]?
2. if I got a Hex value transfer from the host, can I just read the Buffer [0] to get it ?
sorry I am a newbie.
Thank you.
Your received data stored in array TempStorage
You used Buufer[0] (the value 0xFF) for to send data to host