After a few more hours of testing I have figured out how LwIP processes the transmit and receive data. Working code is attached for both processes.
I think mark03's comments about it just being 32-bit words is the key. The comments greenpossum made about assembly or reassembly is true. I was doing the assembly and reassembly in my user code. LwIp does know about the length of the data from memcpy but I had the memcpy statement wrong. Thanks HwAoRrDk for pointing that out. It should have been memcpy(pb->payload, datain, 40); But 40 is not actually the data length as far as LwIP is concerned. Here is where mark03 is correct about "words".
The adcbuffer[] is declared as uint16_t. But LwIP wants 8 bit data to transmit. What I found was that when I copied data from the adcbuff[] to the pbuff, I had to copy twice as many bytes as what the adcbuff[] actually held. Since I was sending 40 uint16_t bytes, I had to actually copy 80 bytes to the pbuf memory.
The STM32F4xx Family Reference manual states this: "The embedded SRAM can be accessed as bytes, half-words (16 bits) or full words (32 bits)." This probably means uint16_t arrays are stored in contiguous half-word locations. That would explain why copying 80 bytes gives the desired transmit action. I ended up using pbuf_take to copy the data instead of memcpy. I tested both and they both work the same but I believe pbuf_take is probably better.
Looking at the code cgroen posted gave me a couple of hints as to how to approach the problem. I don't have to worry about chained pbuffs. I have 1100 bytes allocated for each pbuff and will only be sending 100 bytes at a time. Therefore I don't have to traverse the pbuf data.
In the receive code you can see I determine the length of the incoming pbuf data. That number tells me how many bytes I have to copy into the datain[] buffer. Again the number here is twice the actual datain[] buffer size since the incoming data is in 8 byte chunks.
Any further comments would be welcome. I have managed to learn more about LwIP than what I intended to know. But it may come in handy in the future. Maybe this chain of posts can help someone else who is having problems with LwIP.
// UDP TRANSMIT CODE
/* USER CODE BEGIN PV */
uint16_t adcbuff[40];
uint16_t adcvalue;
uint8_t buffcount;
static struct udp_pcb * test_pcb;
static uint16_t test_port = 3333;
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
void test_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *srcAddr, uint16_t port);
/* USER CODE END PFP */
int main(void)
{
/* USER CODE BEGIN 1 */
uint16_t count, x;
uint8_t ipaddr[] = {172,16,1,122}, maskaddr[] = {255, 255, 255, 0}, gateaddr[] = {172,16,1,1};
IP_ADDR4(&test_destIp, 172, 16, 1, 123);
/* USER CODE END 1 */
for(buffcount=0; buffcount<40; buffcount++)
{
adcbuff[buffcount] = x; // populate array
x += 25;
}
while(1)
{
if(HAL_GPIO_ReadPin(SW1_GPIO_Port, SW1_Pin) == 0)
{
udp_test_send();
HAL_Delay(40); // debounce switch
}
MX_LWIP_Process(); // to check for Ethernet traffic - MX_LWIP_Process function is declared inside lwip.h
}
void udp_test_send(void)
{
struct pbuf * pb = pbuf_alloc(PBUF_TRANSPORT, 80, PBUF_POOL); // set pbuf size to 80
if(!pb)
{
//error!
return;
}
pbuf_take(pb, adcbuff, 80);
udp_sendto(test_pcb, pb, &test_destIp, test_port);
MX_LWIP_Process(); // process send data immediately
HAL_GPIO_TogglePin(GRN_GPIO_Port, GRN_Pin);
pbuf_free(pb);
}
// UDP RECEIVE CODE
/* USER CODE BEGIN PV */
uint16_t datain[40];
uint16_t incount = 0, outcount = 0;
static struct udp_pcb * test_pcb;
static uint16_t test_port = 3333;
ip4_addr_t dest_Ip;
ip4_addr_t local_Ip;
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
void test_recv(void *arg, struct udp_pcb *pcb, struct pbuf *pb, const ip_addr_t *srcAddr, uint16_t port);
/* USER CODE END PFP */
int main(void)
{
uint8_t ipaddr[] = {172,16,1,123}, maskaddr[] = {255, 255, 255, 0}, gateaddr[] = {172,16,1,1};
IP_ADDR4(&dest_Ip, 172, 16, 1, 122);
IP_ADDR4(&local_Ip, 172, 16, 1, 123); // set IP of this board for use in bind
// operation in udp_test_int function
while(1)
{
MX_LWIP_Process(); // check for Ethernet traffic - MX_LWIP_Process function declared inside lwip.h
}
}
// This is a callback function that is called every time ethernet traffic is received
void test_recv(void *arg, struct udp_pcb *pcb, struct pbuf *pb, const ip_addr_t *srcAddr, uint16_t port)
{
uint8_t len;
if(pb != NULL)
{
len = pb->len; // len shows 80 here when running debug session
memcpy(datain, pb->payload, len); //80);
HAL_GPIO_WritePin(RED_GPIO_Port, RED_Pin, 1); //DEBUG CODE
pbuf_free(pb);
}
}